线程安全以及如何避免死锁,线程通信

一,解决线程安全问题--加锁

1,synchronized 自动锁

synchronized () {}

()锁资源-----共享资源作为锁资源.只要使用的是同一把锁资源就可以上锁成功。必须是对象可以是(this或Object)

public class TestTicket {
    public static void main(String[] args) {
         Ticket task=new Ticket();//任务对象

         Thread t1=new Thread(task,"窗口A");
         Thread t2=new Thread(task,"窗口B");
         Thread t3=new Thread(task,"窗口C");
         Thread t4=new Thread(task,"窗口D");

         t1.start();
         t2.start();
         t3.start();
         t4.start();
    }
}

class Ticket implements Runnable {

    private Integer ticket = 100;
    private Object o=new Object(); //新建一个Object做为锁资源
    @Override
    public void run() {
        while (true) {
            synchronized (this) { //()要的是一个对象! tiket它是一个int类型
                if (ticket <= 0) {
                    break;
                }
                ticket--;
                System.out.println(Thread.currentThread().getName() + "卖了一张,剩余:" + ticket + "张");
            }
        }
    }
}

Lock 手动锁

Lock lock = new ReentrantLock();

 lock.lock(); 加锁

lock.unlock();解锁

/**
 * @program: thread02
 * @description:
 * @author: 坤仔
 * @create: 2022-01-05 15:57
 **/
public class Testhelloworld {
    private static String[] arr=new String[5];
    private static int index=0;

    public static void main(String[] args) throws InterruptedException {
        Lock lock = new ReentrantLock();
        Runnable hello = new Runnable(){
            @Override
            public void run() {
                try {
                    lock.lock();//重入锁 可以多次加锁,创建一个手动锁对象
                    if (arr[index]==null){
                        arr[index]="hello";
                        index++;
                    }
                } finally {
                    lock.unlock();//解锁
                }
            }
        };
        Runnable world = new Runnable(){
            @Override
            public void run() {
                try {
                    lock.lock();
                    if (arr[index]==null){
                        arr[index]="world";
                        index++;
                    }
                } finally {
                    lock.unlock();
                }
            }
        };
        Thread t1 = new Thread(hello, "AAA");
        Thread t2 = new Thread(world, "BBB");
        t1.start();
        t2.start();
        t1.join();
        t2.join();
        System.out.println(Arrays.toString(arr));
    }
}

二,死锁以及如何避免死锁

如何避免

1.尽量不要使用锁的嵌套。
2.尽量使用安全类。
3.可以lock锁的tryLock设置锁的时间。 

三,线程通信

唤醒 notify() 随机唤醒等待队列中的一个; notifyAll() 唤醒等待队列中的所有线程 

一存一取

/**
 * @program: thread02
 * @description:
 * @author: 坤仔
 * @create: 2022-01-05 16:22
 **/
public class TestBank {
    public static void main(String[] args) {
        Banck banck = new Banck(0);

        saveMoney saveMoney = new saveMoney(banck);
        takeMoney takeMoney = new takeMoney(banck);

        Thread t1= new Thread(saveMoney, "AAA");
        Thread t2 = new Thread(takeMoney, "BBB");
        t1.start();
        t2.start();
    }
}
class saveMoney implements Runnable{
    private Banck banck;

    public saveMoney(Banck banck) {
        this.banck = banck;
    }

    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            banck.savemoney(1000);
        }
    }
}
class takeMoney implements Runnable{
    private Banck banck;

    public takeMoney(Banck banck) {
        this.banck = banck;
    }

    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            banck.takemoney(1000);
        }
    }
}
class Banck{
    private double balnce;
    private boolean flag=false;

    public Banck(double balnce) {
        this.balnce = balnce;
    }
    public synchronized void savemoney(double money){
        if (flag){
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        balnce+=1000;
        System.out.println(Thread.currentThread().getName()+"存入了1000元;卡中余额:"+balnce);
        flag=true;
        this.notify();
    }
    public synchronized void takemoney(double money){
        if (!flag){
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        balnce-=1000;
        System.out.println(Thread.currentThread().getName()+"取出了1000元;卡中月"+balnce);
        flag=false;
        this.notify();
    }
}

多存多取

/**
 * @program: thread02
 * @description:
 * @author: 坤仔
 * @create: 2022-01-05 16:22
 **/
public class TestBank {
    //多存多取 出现余额变为负数的问题 解决方案 把if改为while 每次唤醒都做判断
    public static void main(String[] args) {
        Banck banck = new Banck(0);

        saveMoney saveMoney = new saveMoney(banck);
        takeMoney takeMoney = new takeMoney(banck);

        Thread t1= new Thread(saveMoney, "AAA");
        Thread t2 = new Thread(takeMoney, "BBB");
        Thread t3= new Thread(saveMoney, "CCC");
        Thread t4 = new Thread(takeMoney, "DDD");
        t1.start();
        t2.start();
        t3.start();
        t4.start();
    }
}

class saveMoney implements Runnable{
    private Banck banck;

    public saveMoney(Banck banck) {
        this.banck = banck;
    }

    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            banck.savemoney(1000);
        }
    }
}

class takeMoney implements Runnable{
    private Banck banck;

    public takeMoney(Banck banck) {
        this.banck = banck;
    }

    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            banck.takemoney(1000);
        }
    }
}

class Banck{
    private double balnce;
    private boolean flag=false;

    public Banck(double balnce) {
        this.balnce = balnce;
    }
    public synchronized void savemoney(double money){
        if(flag){
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        balnce+=1000;
        System.out.println(Thread.currentThread().getName()+"存入了1000元;卡中余额:"+balnce);
        flag=true;
        this.notify();
    }
    public synchronized void takemoney(double money){
        if(!flag){
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        balnce-=1000;
        System.out.println(Thread.currentThread().getName()+"取出了1000元;卡中月"+balnce);
        flag=false;
        this.notify();
    }
}

结果

 结果

if改为while

public class TestBank {
    //多存多取 出现余额变为负数的问题 解决方案 把if改为while 每次唤醒都做判断
    public static void main(String[] args) {
        Banck banck = new Banck(0);

        saveMoney saveMoney = new saveMoney(banck);
        takeMoney takeMoney = new takeMoney(banck);

        Thread t1= new Thread(saveMoney, "AAA");
        Thread t2 = new Thread(takeMoney, "BBB");
        Thread t3= new Thread(saveMoney, "CCC");
        Thread t4 = new Thread(takeMoney, "DDD");
        t1.start();
        t2.start();
        t3.start();
        t4.start();
    }
}

class saveMoney implements Runnable{
    private Banck banck;

    public saveMoney(Banck banck) {
        this.banck = banck;
    }

    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            banck.savemoney(1000);
        }
    }
}

class takeMoney implements Runnable{
    private Banck banck;

    public takeMoney(Banck banck) {
        this.banck = banck;
    }

    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            banck.takemoney(1000);
        }
    }
}

class Banck{
    private double balnce;
    private boolean flag=false;

    public Banck(double balnce) {
        this.balnce = balnce;
    }
    public synchronized void savemoney(double money){
        while (flag){
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        balnce+=1000;
        System.out.println(Thread.currentThread().getName()+"存入了1000元;卡中余额:"+balnce);
        flag=true;
        this.notify();
    }
    public synchronized void takemoney(double money){
        while (!flag){
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        balnce-=1000;
        System.out.println(Thread.currentThread().getName()+"取出了1000元;卡中月"+balnce);
        flag=false;
        this.notify();
    }
}

结果:

 改善  使用notifyAll替换notify

/**
 * @program: thread02
 * @description:
 * @author: 坤仔
 * @create: 2022-01-05 16:22
 **/
public class TestBank {
    //多存多取 出现余额变为负数的问题 解决方案 把if改为while 每次唤醒都做判断
    public static void main(String[] args) {
        Banck banck = new Banck(0);

        saveMoney saveMoney = new saveMoney(banck);
        takeMoney takeMoney = new takeMoney(banck);

        Thread t1= new Thread(saveMoney, "AAA");
        Thread t2 = new Thread(takeMoney, "BBB");
        Thread t3= new Thread(saveMoney, "CCC");
        Thread t4 = new Thread(takeMoney, "DDD");
        t1.start();
        t2.start();
        t3.start();
        t4.start();
    }
}

class saveMoney implements Runnable{
    private Banck banck;

    public saveMoney(Banck banck) {
        this.banck = banck;
    }

    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            banck.savemoney(1000);
        }
    }
}

class takeMoney implements Runnable{
    private Banck banck;

    public takeMoney(Banck banck) {
        this.banck = banck;
    }

    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            banck.takemoney(1000);
        }
    }
}

class Banck{
    private double balnce;
    private boolean flag=false;

    public Banck(double balnce) {
        this.balnce = balnce;
    }
    public synchronized void savemoney(double money){
        while (flag){
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        balnce+=1000;
        System.out.println(Thread.currentThread().getName()+"存入了1000元;卡中余额:"+balnce);
        flag=true;
        this.notifyAll();
    }
    public synchronized void takemoney(double money){
        while (!flag){
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        balnce-=1000;
        System.out.println(Thread.currentThread().getName()+"取出了1000元;卡中月"+balnce);
        flag=false;
        this.notifyAll();
    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值