博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
多线程--线程不安全和线程死锁,同步锁Synchronize
阅读量:2049 次
发布时间:2019-04-28

本文共 3439 字,大约阅读时间需要 11 分钟。

线程不安全和线程死锁、同步锁Synchronize

什么叫线程不安全?

当多个线程共享同一个资源时,在不使用同步锁的情况下对共享资源进行读写操作是,导致的程序执行结果异常,产生不正常的结果数据。

举个例子:两个人去抢票,当强到最后一张的时,在两个人眼里都看见有一张票,于是两个同时去抢,结果两个人都抢到了,而票的数量变成的-1。

解决线程不安全的办法?

解决线程不安全的办法就是给线程加锁,使用线程同步机制synchronize。线程同步其实就是个等待机制,多个线程访问同一个资源时,就要让这些线程进入一个等待池形成队列,等待前一个线程使用完毕,下一个线程使用。

在这里插入图片描述
排队使用机制。

Synchronize同步锁

形成机制:队列 + 锁

当一个线程获取到对象的排它锁时,其他线程必须等待,等该线程结束使用(打开锁)时才能使用。
使用同步锁容易产生的问题?

  • 线程必须要等待上一个线程结束才能使用,会导致程序效率问题。
  • 在多线程且有多个资源对象锁的使用情况下,可能会产生一个线程占用了另一个进程的待使用资源,而处于一直等待该线程释放锁的状态,如果该线程一直占用锁,那么就会产生线程死锁问题。
  • 如果一个优先级高的线程等待一个优先级底的线程释放锁,会影响性能问题(比如很多个简单线程都在等一个复杂线程处理事务结束,就会影响执行效率)。

Synchronize同步锁:同步方法 和 同步代码块

同步方法 默认锁为this(当前对象),任何对象都能成为锁。

private synchronized  void buyTicket() {        System.out.println(Thread.currentThread().getName() + ":我抢到了一个票" + ticketnum--);        // 控制线程结束        if (ticketnum <= 0) {            falg = false;        }    }

同步代码块 :一般将共享资源或者需要被操作的资源对象作为锁。

private   void buyTicket() {        synchronized (this){   // Obj 代表任何资源对象            System.out.println(Thread.currentThread().getName() + ":我抢到了一个票" + ticketnum--);            // 控制线程结束            if (ticketnum <= 0) {                falg = false;            }        }    }

PS:线程sleep方法是让线程休息等待,不释放锁。wait是让线程进入等待区,释放锁。

什么是线程死锁?

线程死锁其实在上面已经提到过了。多个线程在共享一些共同资源的情况下,且拥有两个以上锁,而都在等待着对方释放锁,导致的线程处于一直等待状态。

举例:我有笔,但是我需要你的纸才能写字,而你需要我的笔才能写字。但是我们都等着对放给自己,导致的一直等待状态。
实现:

// 笔对象class Pen{}// 纸对象class Paper{}// 写字class Write implements Runnable{    static  Pen pen = new Pen();    static  Paper paper = new Paper();    int flag;    String name;    Write(int flag,String name){         this.flag = flag;         this.name = name;    }    @Override    public void run() {        try {            writeWork();        } catch (InterruptedException e) {            e.printStackTrace();        }    }public  void writeWork() throws InterruptedException {        // 当flag 0时获取笔        if(flag==0){             synchronized (pen){                System.out.println(name+":拿到了笔");                Thread.sleep(2000);                // 然后去拿纸的锁                 synchronized (paper){                     System.out.println(name+":拿到了纸");                 }             }        }else {            synchronized (paper){                System.out.println(name+":拿到了纸");                Thread.sleep(2000);                // 然后去拿纸的锁                synchronized (pen){                    System.out.println(name+":拿到了笔");                }            }        }    }}/** * Created by 一只会飞的猪 on 2021/3/8. * 实现线程死锁现象,写字 = 笔 + 纸 */public class DeadLockThread {    public static void main(String[] args) {        new Thread(new Write(0,"小美")).start();        new Thread(new Write(1,"小丑")).start();    }}

结果:小美和小丑都拿着自己的锁,等终身。

在这里插入图片描述
怎么解决死锁呢?
解决死锁没有什么好的办法,一般都是根据业务需求,准备的对对象进行锁和释放锁处理。比如上例。
我们只要让两个人拿到一个资源之后释放锁,再去取另一个资源就行。

public  void writeWork() throws InterruptedException {        // 当flag 0时获取笔        if(flag==0){             synchronized (pen){                System.out.println(name+":拿到了笔");                Thread.sleep(2000);             }            // 然后去拿纸的锁            synchronized (paper){                System.out.println(name+":拿到了纸");            }        }else {            synchronized (paper){                System.out.println(name+":拿到了纸");                Thread.sleep(2000);            }            // 然后去拿纸的锁            synchronized (pen){                System.out.println(name+":拿到了笔");            }        }    }

结果:两个人都能愉快。

在这里插入图片描述
PS: Synchronize同步锁(隐式同步),在实行完作用域之后,会自动释放锁。而Lock锁(下片),需要主动释放锁(显示同步)

转载地址:http://jjhof.baihongyu.com/

你可能感兴趣的文章
分析C语言的声明
查看>>
TCP为什么是三次握手,为什么不是两次或者四次 && TCP四次挥手
查看>>
C结构体、C++结构体、C++类的区别
查看>>
进程和线程的概念、区别和联系
查看>>
CMake 入门实战
查看>>
绑定CPU逻辑核心的利器——taskset
查看>>
Linux下perf性能测试火焰图只显示函数地址不显示函数名的问题
查看>>
c结构体、c++结构体和c++类的区别以及错误纠正
查看>>
Linux下查看根目录各文件内存占用情况
查看>>
A星算法详解(个人认为最详细,最通俗易懂的一个版本)
查看>>
利用栈实现DFS
查看>>
逆序对的数量(递归+归并思想)
查看>>
数的范围(二分查找上下界)
查看>>
算法导论阅读顺序
查看>>
Windows程序设计:直线绘制
查看>>
linux之CentOS下文件解压方式
查看>>
Django字段的创建并连接MYSQL
查看>>
div标签布局的使用
查看>>
HTML中表格的使用
查看>>
(计蒜客)骑马走江湖(BFS加剪枝)
查看>>