0

只是为了练习,我想将 java synchronized 关键字实现为 java 对象。你会说下面的代码是一个很好的设计吗?我猜 AtomicReference 的性能与 AtomicBoolean 相似?

建议后更新代码:

public class SynchronizedBlock implements Runnable{

private final Lock lock;
private final Runnable runnable;

public SynchronizedBlock(Runnable r, Lock l){
    runnable = r;
    lock = l;
}

public void run() {
    try {
        while(!lock.compareAndSet(false, true)){
            Thread.sleep(100);
        }
        runnable.run();
    } catch (InterruptedException e) {
        e.printStackTrace();
    } finally {
        lock.unlock();
    }


}

 }

 public class Lock {
private final AtomicReference<Boolean> locked = new AtomicReference<Boolean>(false);

public boolean compareAndSet(boolean expected, boolean update){
    return locked.compareAndSet(expected, update);
}

public boolean isLocked(){
    return locked.get();
}

public void unlock(){
    locked.set(false);
}
 }

@Test
public void test() {



    final SynchronizedBlock sb = new SynchronizedBlock(new Runnable(){

        public void run() {
            x++;
            System.out.println(x);
        }

    }, new Lock());

    Runnable r1 = new Runnable(){

        int c = 0;
        public void run() {
            while(c<10){
                sb.run();
                c++;
            }
        }

    };

    Runnable r2 = new Runnable(){

        int c = 0;
        public void run() {
            while(c<10){
                sb.run();
                c++;
            }
        }

    };

    Thread t1 = new Thread(r1);
    Thread t2 = new Thread(r2);

    t1.start();
    t2.start();

    while (t1.isAlive() && t2.isAlive()){

    }

    assertEquals(20,x);

}
4

2 回答 2

1

您应该添加一个方法来封装 compareAndSwap,并且在尝试获取锁之前没有必要循环释放锁。为什么会遇到这样的情况:您可以看到锁是空闲的,但是当您尝试使用它时,它已经消失了。

我会删除 lock 方法并将解锁放在 finally 锁中,这样异常/错误就不会导致永远不会解锁的锁。

我也会使用比 AtomicReference 更自然的 AtomicBoolean

于 2013-10-06T17:56:01.077 回答
0

首先也是最重要的,你应该删除Thread.sleep(100). 即使仅在 2 线程争用中,这也会导致至少 100 毫秒的延迟。

您可以简单地使用AtomicBoolean而不是AtomicReference来简化您的代码。此外,如果您真的担心高争用情况下的并发性,您可以在执行 CAS 之前修改您的代码以检查它是否被锁定。

while (true) {
  if (lock.isLocked()) continue; // or get() == true if you use AtomicBoolean
  if (lock.compareAndSet(false, true)) 
    break;
}

这是 TTAS(Test-Test-And-Set)锁定的一个示例,它利用本地自旋来减少循环时的主内存访问。见http://en.wikipedia.org/wiki/Test_and_Test-and-set

于 2013-10-08T07:36:52.923 回答