Java structured lock vs unstructured lock

此页面是否是列表页或首页?未找到合适正文内容。

Java structured lock vs unstructured lock

标签:stscalling内存removecalhead代码err方法

什么是structured lock?先来段代码:

public synchronized boolean contains(final Integer object) {
Entry pred = this.head;
Entry curr = pred.next;

while (curr.object.compareTo(object) < 0) {
pred = curr;
curr = curr.next;
}
return object.equals(curr.object);
}

这段代码用synchronized来解决并发问题,这个例子是在方法上上锁,也就是object级别,那么一旦这个object被上锁,该object的所有同步方法都会被锁,锁被释放的时机是方法执行完毕,提到synchronized,也顺便提一下wait/notify好了,看以下代码:

public class Main {
public static void main(String[] args){
ThreadB b = new ThreadB();
b.start();

synchronized(b){
try{
System.out.println(\”Waiting for b to complete…\”);
b.wait();
}catch(InterruptedException e){
e.printStackTrace();
}

System.out.println(\”Total is: \” + b.total);
}
}
}

class ThreadB extends Thread{
int total;
@Override
public void run(){
synchronized(this){
try {
sleep(2000);
} catch (InterruptedException e) {
System.out.println(\”wokao\”);
}
for(int i=0; i<100 ; i++){
total += i;
}
notify();
}
}
}

  (这个程序一般运行不会有问题,但有个潜在的bug,谁能看出来)结合这个例子,两句话基本能解释

  • wait()tells the calling thread to give up the monitor and go to sleep until some other thread enters the same monitor and calls notify( ).
  • notify()wakes up the first thread that calledwait()on the same object.
  • 这种synchronized对同步机制,又称为structured lock,因为看起来很结构化,很规整有没有?

    但是结果化对应对结果就是不够灵活。什么时候需要灵活呢?举个例子

    有这么个链表A->B->C->D->E->F

    假设有如下一组工作:

    1.写A和B;

    2.写B和C

    3.写C和D

    4.写D和E

    5.写E和F

    如果用synchronized把1中的A和B锁了,那么2就必须等A和B都执行完成才能,执行,但是有必要吗?其实只要等A结束,2就应该可以执行了,依次往下,这就是所谓的hand in hand locking,

    就是连环锁,描述如下:

    lock A and B, start job 1

    unlock A, lock C, start job 2

    unlock B, lock D, start job 3 …

    这种连环锁,显然synchronized是做不到的,sychronized里面可以套其他的synchronized,那只能形成一个nested结构。

    这就是synchronized或者说structured lock的局限性。

    那么这种情况下 unstructured lock就有用了,看一个使用的例子:

    public static final class CoarseList extends ListSet {
    /*
    * TODO Declare a lock for this class to be used in implementing the
    * concurrent add, remove, and contains methods below.
    */
    ReentrantLock lk= new ReentrantLock();

    /**
    * Default constructor.
    */
    public CoarseList() {
    super();
    }

    /**
    * {@inheritDoc}
    *
    * TODO Use a lock to protect against concurrent access.
    */
    @Override
    boolean add(final Integer object) {
    try{
    lk.lock();
    Entry pred = this.head;
    Entry curr = pred.next;

    while (curr.object.compareTo(object) < 0) {
    pred = curr;
    curr = curr.next;
    }

    if (object.equals(curr.object)) {
    return false;
    } else {
    final Entry entry = new Entry(object);
    entry.next = curr;
    pred.next = entry;
    return true;
    }
    }finally {
    lk.unlock();
    }

    }

      

    这里的ReentrantLock就很灵活,不过必须显式地unlock,否则会出问题(就像c++必须显示delete内存一样),为了防止意外例如抛出exception,应该把unlock语句放在finally里,所以这里的弊端想必也能看到了吧,到处都要写try finally语句!!!

    作者: liuzhihao

    为您推荐

    返回顶部