Java 多线程(2) 线程同步 死锁

线程同步

指多个线程操作同一个资源,即并发
处理这种问题就需要用到线程同步机制,多个线程同时访问此对象会进入这个对象的等待队列,一个一个来。 同时为了保证安全,除了队列还要加上锁机制。

通过同步解决买票问题

//多个线程操作同一个对象
public class ThreadDemo3 implements Runnable{
    private int tickNums=10;
    boolean flag=true;
    public void  run() {
       while(flag){
           try{
               Thread.sleep(200);
           } catch (InterruptedException e) {
               e.printStackTrace();
           }
           buy();
       }
    }
    private synchronized  void buy()  {//加上了synchronized关键字
        if(tickNums<=0){
            flag=false;
            return;
        }
        System.out.println(Thread.currentThread().getName()+"拿到了第"+tickNums--+"票");
    }
    public static void main(String[] args) {
        ThreadDemo3 threadDemo3=new ThreadDemo3();
        new Thread(threadDemo3,"小明").start();
        new Thread(threadDemo3,"小红").start();
        new Thread(threadDemo3,"小蓝").start();
    }
}

同步块

死锁


代码例子

public class DeadLockDemo {
    public static void main(String[] args) {
        UseItem useItem1=new UseItem(0,"小明");
        UseItem useItem2=new UseItem(1,"小红");
        useItem1.start();
        useItem2.start();
    }
}
class ItemA{}
class ItemB{}
class UseItem extends Thread{
    static ItemA itemA=new ItemA();
    static ItemB itemB=new ItemB();
    //通过static保证只有一份
    int num;//
    String username;
    UseItem(int num,String username){
        this.num=num;
        this.username=username;
    }
    private void useitem() throws InterruptedException {
        if(num==0){//编号为0的人
            synchronized (itemA){//使用A物品 即锁了A
                System.out.println(this.username+"在使用物品A");
                Thread.sleep(1000);//通过sleep 模拟用物品一秒
                synchronized (itemB){
                    System.out.println(this.username+"在使用物品B");
                }
            }
        }
        else {
            synchronized (itemB){
                System.out.println(this.username+"在使用物品B");
                Thread.sleep(2000);//通过sleep 模拟用物品两秒
                synchronized (itemA){
                    System.out.println(this.username+"在使用物品A");
                }
            }
        }
    }
    @Override
    public void run() {
        try {
            useitem();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}

运行上面代码就会出现死锁
解决方法
避免一个synchronized块里出现两种对象的锁

public class DeadLockDemo {
    public static void main(String[] args) {
        UseItem useItem1=new UseItem(0,"小明");
        UseItem useItem2=new UseItem(1,"小红");
        useItem1.start();
        useItem2.start();
    }
}
class ItemA{}
class ItemB{}
class UseItem extends Thread{
    static ItemA itemA=new ItemA();
    static ItemB itemB=new ItemB();
    //通过static保证只有一份
    int num;//
    String username;
    UseItem(int num,String username){
        this.num=num;
        this.username=username;
    }
    private void useitem() throws InterruptedException {
        if(num==0){//编号为0的人
            synchronized (itemA){//使用A物品 即锁了A
                System.out.println(this.username+"在使用物品A");
                Thread.sleep(1000);//通过sleep 模拟用物品一秒
            }
            synchronized (itemB){
                System.out.println(this.username+"在使用物品B");
            }
        }
        else {
            synchronized (itemB){
                System.out.println(this.username+"在使用物品B");
                Thread.sleep(1000);//通过sleep 模拟用物品两秒
            }
            synchronized (itemA){
                System.out.println(this.username+"在使用物品A");
            }
        }
    }
    @Override
    public void run() {
        try {
            useitem();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}

LOCK锁


通过lock锁解决买票问题

import java.util.concurrent.locks.ReentrantLock;

public class LockDemo {
    public static void main(String[] args) {
        BuyTicket buyTicket=new BuyTicket();
        new Thread(buyTicket,"小明").start();
        new Thread(buyTicket,"小红").start();
        new Thread(buyTicket,"小绿").start();
    }
}
class BuyTicket implements Runnable{
    private int num=50;
    private boolean flag=true;
    //定义lock
    private ReentrantLock lock=new ReentrantLock();
    public void stop(boolean flag) {
        this.flag =false;
    }
    private void buy(){
        while(flag){
                try{
                    Thread.sleep(1000);
                    lock.lock();//上锁
                    if(num<=0){
                        flag=false;
                        break ;
                    }
                    else {
                        System.out.println(Thread.currentThread().getName()+"买了第"+num--+"票");
                    }
                }
                catch (Exception e) {
                    e.printStackTrace();
                }
                finally {
                    lock.unlock();//解锁
                }
        }
    }
    @Override
    public void run() {
        buy();
    }
}

解决生产者消费者问题

https://www.cnblogs.com/OfflineBoy/p/14613402.html

posted @ 2021-04-02 12:14  一个经常掉线的人  阅读(64)  评论(0)    收藏  举报