本文共 3439 字,大约阅读时间需要 11 分钟。
当多个线程共享同一个资源时,在不使用同步锁的情况下对共享资源进行读写操作是,导致的程序执行结果异常,产生不正常的结果数据。
举个例子:两个人去抢票,当强到最后一张的时,在两个人眼里都看见有一张票,于是两个同时去抢,结果两个人都抢到了,而票的数量变成的-1。解决线程不安全的办法就是给线程加锁,使用线程同步机制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/