Tips: Transient--序列化时,不会把信息序列化; volatile保证可见性
cellsBusy类似cas锁,作为j加锁的标记,0表示未加锁,1表示加锁。保护对某些资源访问时的线程安全。保护cell数组在不同线程上创建和扩容时的线程安全。用while true进行保护。
Cell累加单元类
CAS锁原理
可直接用封装好的codes,不能直接使用,严重影响性能。
import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.atomic.AtomicInteger;
@Slf4j(topic = "TC34")
public class TC34 {
//0 无锁
//1 有锁
private AtomicInteger state = new AtomicInteger(0);
private void lock() {
while(true) {
//如果lock值是0,那么把它赋值为1。变成有锁的
if (state.compareAndSet(0,1)) {
break;
}
}
}
private void unlock() {
log.debug("unlocking.....");
state.set(0);
}
//cas 锁原理
public static void main(String[] args) {
TC34 lock = new TC34();
new Thread(()->{
log.debug("Begin.....");
lock.lock();
try{
log.debug("lock....");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}finally {
lock.unlock();
}
},"t1").start();
new Thread(()->{
log.debug("Begin.....");
//等待t1线程将lock状态改为0,才能加锁成功,于是这里不停的进行while true循环。保证线程安全
lock.lock();
try{
log.debug("lock....");
}finally {
lock.unlock();
}
},"t2").start();
}
}
原理之伪共享
一个缓存行加了多个Cell对象,当一个CPU修改一个对象时,另一个对象在其他CPU缓存行中被影响,此类现象为伪共享。
避免伪共享:@sun.misc.Contended
内存等级:cpu中有寄存器
当数据存入内存中,cpu读取时,会将内存中的数据拷贝到缓存中,两个cpu则拷贝两份数据到不同的缓存中。如果其中一份缓存数据被修改,那么另一个缓存行就会失效。
当第一个CPU修改cell[0]的数值时,会使CPU2中的缓存行失效,这时又要修改CPU2中的值。
当数组中的值存在于不同的缓存行时,就可以避免此类问题的产生,@sun.misc.Contended可以实现这个目的。