线程同步(线程安全处理Synchronized)与死锁

线程同步(线程安全处理Synchronized)与死锁

一  线程同步

java中提供了线程同步机制,它能够解决上述的线程安全问题。

         线程同步的方式有两种:

方式1:同步代码块

  方式2:同步方法

1 同步代码块

同步代码块: 在代码块声明上 加上synchronized

synchronized (锁对象) {
    可能会产生线程安全问题的代码
}

同步代码块中的锁对象可以是任意的对象;但多个线程时,要使用同一个锁对象才能够保证线程安全。

使用同步代码块,对电影院卖票案例中Ticket类进行如下代码修改

package com.oracle.demo01;

public class Myticket implements Runnable {
    private int ticket=100;
    private Object obj=new Object();
    public void run() {
        while(true){
            synchronized (obj) {
            if(ticket>0){
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName()+"出售第"+ticket--+"张票");
            }
            }
        }
    }
    
}

运行结果为:

线程同步(线程安全处理Synchronized)与死锁

这样就解决了线程安全的问题

2  同步方法

  同步方法:在方法声明上加上synchronized

public synchronized void method(){
       可能会产生线程安全问题的代码
}

同步方法中的锁对象是 this

使用同步方法,对电影院卖票案例中Ticket类进行如下代码修改:

package com.oracle.demo01;

public class Myticket2 implements Runnable {
    private int ticket=100;
    //同步方法是否有锁对象?有   this
    //静态同步方法有锁对象?有,MyTicket2.class
    //同步怎么保证安全性?没有锁的线程不能执行只能等
    //加了同步,线程进同步判断锁的时候,比如,获取锁,释放锁,导致运行速度慢
    //StringBuilder比StringBuffer快的原因
    //StringBuffer里面的所有方法都加了同步关键字,所以慢,但安全
    //StringBuilder是没有的,所以快,但不安全
    public synchronized void sale(){
        //可能会产生线程安全问题的代码
        if(ticket>0){
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+"出售第"+ticket--+"张票");
        }
    }
    public void run() {
        while(true){
            sale();
        }
    }
    
}

二  死锁

同步锁使用的弊端:当线程任务中出现了多个同步(多个锁)时,如果同步中嵌套了其他的同步。这时容易引发一种现象:程序出现无限等待,这种现象我们称为死锁。这种情况能避免就避免掉。

线程同步(线程安全处理Synchronized)与死锁

package com.oracle.demo02;

public class DeadLock implements Runnable {
    private int i=0;
    public void run() {
        while(true){
            if(i%2==0){
                //先进A同步,再进B同步
                synchronized (LockA.locka) {
                    System.out.println("if...locka");
                    synchronized (LockB.lockb) {
                        System.out.println("if...lockb");
                    }
                }
            }else{
                //先进B同步,再进A同步
                synchronized (LockB.lockb) {
                    System.out.println("else...lockb");
                    synchronized (LockA.locka) {
                        System.out.println("else...locka");
                    }
                }
            }
            i++;
        }
    }
}

程序无线等待

线程同步(线程安全处理Synchronized)与死锁