并发编程实战读书笔记(一)线程安全性

本章内容:
1、什么是线程安全?
2、解决线程安全的几种方式?
3、加锁的机制

1、什么是线程安全?
多个线程访问某个类时,不管运行环境以何种调度方式或者这些线程如何交替执行,并且在主代码中不需要额外的同步或者协同,这个类都能表现出正确的行为,那么这个类就是线程安全的。如http请求,处理类内部只使用局部变量就是线程安全的。比如做一个调用计数,每个线程都加一这种就是不安全的。但对于http请求来说,无状态的本身就是线程安全的。
2、解决线程安全的几种方式?
synchronized、Lock、volatile、Atomic*等几种方式
3、加锁的机制?
1)内置锁,相当于互斥锁
持有锁的线程运行时,其他线程阻塞直到持有锁的线程释放锁。
进入锁的代码块自动获得锁,退出代码块自动释放锁。
例:
    private  static Object lock = new Object();
    public static void main(String[] args) throws InterruptedException {
        new Thread(() -> {
            String name = Thread.currentThread().getName();
            synchronized (lock) {
                System.out.println("thread : " + name + " start....");
                while(true){
                    System.out.println(name + " dead loop");
                }
            }
        }).start();
        
        new Thread(() -> {
            String name = Thread.currentThread().getName();
            System.out.println("thread : " + name + " start....");
            synchronized (lock) {
                while(true){
                    System.out.println(name + " dead loop");
                }
            }
        }).start();
        
        TimeUnit.SECONDS.sleep(Long.MAX_VALUE);
    }
2)重入。内置锁是可重入的
当某个线程访问其他线程持有的锁时,发出请求的线程会阻塞。然而如果某个线程试图获取由它自己持有的锁,这个请求会成功。如以下示例,程序正常运行,说明内置锁是可重入的。
重入实现逻辑:对于每个锁对应一个Count和持有线程。当count==0这个锁没有被任何线程持有,当线程请求一个未被持有的锁,JVM记录锁的持有者并count=1.如果同一个线程再次获取这个锁则Count++ ,而当线程退出同步代码块则计数器会相应减少。当count =0 时锁释放。
如果是不可重入锁,这种逻辑会发生死锁
public class Reet {

    public static void main(String[] args) {
        
        FinalProcess finalProcess = new FinalProcess();
        finalProcess.process();
    }
}
interface IProcess{
    void process();
}
class Process implements IProcess{
    @Override
    public synchronized void process() {
        System.out.println("Process !");
    }
}

class FinalProcess extends Process{
    @Override
    public synchronized void process() {
        super.process();
        System.out.println("FinalProcess !");
    }
}
3)用锁来保护状态。
如果只是保证某个变量原子性Atomic*即可,但是对于多个变量(尤其是还有联动关系)时,需要我们保证一段代码串行化。这时需要锁,但是需要注意的是如果针对相同变量组合有多个代码块需要同步,则需要同一个锁来保护。
比如:
方法1:代表几个变量增加的逻辑
方法2:代表几个变量减少的逻辑。这两方法加的锁要是同一个
4)活跃性与性能
就是同步的代码块的区域大小。理想状态是尽量减小范围,做好线程安全和程序性能的兼顾


 

发布了82 篇原创文章 · 获赞 8 · 访问量 8914

猜你喜欢

转载自blog.csdn.net/MrBack/article/details/104646142
今日推荐