《java并发编程实战》之 线程安全性

1.线程安全性

当多个线程访问某个类时,不管运行时环境采用何种调度方式或者这些线程将如何交替执行,并且在主调代码中不需要任何额外的同步或协同,这个类都能表现出正确的行为,那么这个类就是线程安全的。

无状态对象一定是线程安全的,何为无状态,就是类中不包含任何域,也不包含各种其他类的饮用,就只有局部变量 。

2.原子性

线程中的 ++count 或者 count++ 那都非原子性,而是  读取--修改--写入,
如果过程中有两个线程在跑,由于不恰当的执行时序出现不正确的结果称为  “竞态条件”

2.1 竞态条件

public class A{
    private B b = null;
    
    public B get(){
        if(b == null)     // thread1,thread2 同时判断为null
            b = new B();
        return b ;
    }
} 

2.3 复合操作

避免竞态条件问题,就要a线程在修改变量时,b线程已经执行完,或者不执行。

对同一个状态有A B 操作,一个线程执行A操作,另一个线程执行B操作,要么是已经执行完,要不就是完全不执行,A B操作都是原子操作。


++count 是复合操作,要以线程安全的方式去修复执行。

使用线程安全的对象进行记录

public class A{
    private final AtomicLong count = new AtomicLong(0);
    
    public long getCount(return count.get());
    
    public void set(){
        count.incrementAndGet();
    }
} 

3.加锁机制

3.1 内置锁(同步代码块 synchronized)

同步代码块
synchronized(lock){
    //访问或修改由锁保护的共享状态
}


某个线程可以重如自己持有的锁的代码中,每个锁有一个计数器,所有者线程,计数器值=0
,锁未被持有,线程请求未被持有的锁,jvm记下锁持有者,计数器值+1, 同一个线程再次获得锁,计数值+1,线程退出,则-1.



public class A{
    public synchronized void do{
        ...
    }
}



public class B extends A{
    public synchronized void do{
        super.do();   //同一个对象,可以多次重入加锁的代码。
    }
}

猜你喜欢

转载自blog.csdn.net/sinat_24230393/article/details/84112874