线程同步--java学习笔记

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/weixin_44494648/article/details/99654742

多个线程并行时容易引发并发问题

当多条线程处理同一份资源时,就容易引发线程安全问题,就是并发问题,

1. 同步块

使用synchronized (){}包裹一段代码,这个处理被称为同步代码块,
格式

//obj是一个对象,
synchronized( Obj){

		......
		//这里就是同步代码块
}

Obj叫做监视器 ,线程开始执行这里时,必须先获得同步代监视器的锁定,一个线程执行完成之后,就会释放对监视器的锁定,这时其他的线程才可以访问这段代码,这样就可以保证只有一个线程访问共享资源,就不会出现错误了,相当于一个人进去,锁了门,其他人排队等候,保证了安全,不会多个线程同时处理。但是要注意,选作监视器的类,在不同的线程访问时,必须时同一个监视器,不然,就是失去了锁的意义

2. 同步方法

用sychronized修饰方法,方法就变成了一个同步方法,对于一个非static方法,监视器就是this ,就是调用刚发的对象,同步方法可以方便的实现线程安全的类,
一个线程安全的类:
该类的对象可以被多个线程安全访问
调用该类的任何方法,都可以得到一个正确的结果
每个线程调用该对象的任何方法,该对象依然保持合理的状态

加了锁的方法一次只允许一个线程执行

3、释放同步监视器的锁定

下面情况会释放同步监视器的锁定

  • 同步代码块中的语句执行结束,或遇到break,return 等结束类其中的运行
  • 出现了error或抛出Exception或方法异常结束
  • 执行了监视器的wait()的方法,当前线程暂停,释放监视器

下面情况不会释放

  • 调用了sleep(0方法,yield()方法,线程会暂停但不会释放监视器的锁定。
  • 其他线程使用了suspend()将线程挂起,县城不会释放监视器

死锁

我们要尽量避免死锁
假如有两个线程各自都拿到了一个对方需要的锁,同时又各自需要对方的锁,两方因为无法得到需要的锁,都无法先释放自己拿到的锁,此时线程就在等待,不结束也不抛异常,只是阻塞状态。

//用来创建监视器
class A{

}
public class Demo01 {
    public static void main(String[] args) {
    //两个监视器
        A a=new A();
        A b=new A();
        //这个线程先使用a锁,后使用b锁,之后再释放b,在释放a
        new Thread(
                ()->{
                    synchronized (a){
                        try {
                        //停一下,放大锁住的概率
                            Thread.sleep(1000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        准备拿b锁
                        synchronized (b){

                        }
                    }
                }
        ).start();
    //这个线程先使用b锁,后使用a锁,之后再释放a,在释放b
        new Thread(
                ()->{
                    synchronized (b){
                        try {
                            Thread.sleep(1000);//放大概率
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        准备拿a锁
                        synchronized (a){

                        }
                    }
                }
        ).start();
    }
}

这时,线程1,先拿到a,准备拿b,线程2,先拿到b准备拿a,但是,要拿的却都被对方拿了,都在等对方放手,自己拿到,再结束线程,但都拿不到,所以就僵住了,都阻塞了。
使用多线程时,要注意处理并发时适当枷锁,但也要注意出现死锁。

猜你喜欢

转载自blog.csdn.net/weixin_44494648/article/details/99654742