@ThreadSafe
public class SafeSequene{
private final AtomicLong value = new AtomicLong(0);
//返回一个唯一的数值
public long getNext(){
return value.incrementAndGet();
}
}
在 java.util.concurrent.atomic 包中,包含了一些原子变量类,用于实现在数值和对象引用上的原子状态转换。通过用 AtmoicLong 来代替 long 类型的计数器,能够确保所有对计数器状态的访问都是原子的。因此也是线程安全的。
@NotThreadSafe
public class CompareValue{
private final AtomicLong value1 = new AtomicLong(0);
private final AtomicLong value2 = new AtomicLong(0);
//返回连个数值是否相等
public boolean isEqual(){
return value1.incrementAndGet() == value2.incrementAndGet();
}
}
实际上,这种方式并不能保证 isEqual 一定返回 true,即使是采用了线程安全类 AtmoicLong。原因是这里涉及多个变量,各个变量是彼此独立的,我们只能保证变量各自的自增操作是原子的;不能保证两个变量同时以原子的方式一起自增。线程 A 在获取 value1 后,可能线程 B 又同时修改了 value2。导致 A 获取到的是 B 修改后的值。
Java 的内置锁是一种互斥锁,这表示最多只有一个线程能持有这种锁。当线程 A 尝试获取线程 B 持有的锁时,线程 A 必须等待或者阻塞,知道 B 释放了这个锁。
这种同步机制,使得上节提到的例子,CompareValue 变得安全,能确保两个变量永远相等。线程 A 调用 isEqual() 时,线程 B 必须等待知道线程 A 调用完成释放锁。
@NotThreadSafe
public class CompareValue{
private final AtomicLong value1 = new AtomicLong(0);
private final AtomicLong value2 = new AtomicLong(0);
//返回一个唯一的数值
public synchronized boolean isEqual(){
return value1.incrementAndGet() == value2.incrementAndGet();
}
}
//如果内置锁不是可重入的,那么这段代码将发生死锁
public class Base {
public synchronized void doSomething() {
....
}
}
public class Child extends Base{
public synchronized void doSomething() {//重写
super.doSomething();//直接调用父类方法
}
}