博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
java多线程(死锁,lock接口,等待唤醒机制)
阅读量:5129 次
发布时间:2019-06-13

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

一.Lock接口

常用方法

Lock提供了一个更加面对对象的锁,在该锁中提供了更多的操作锁的功能。

使用Lock接口,以及其中的lock()方法和unlock()方法替代同步,对电影院卖票案例中Ticket类进行如下代码修改:

 

public class Ticket implements Runnable {    //共100票    int ticket = 100;        //创建Lock锁对象    Lock ck = new ReentrantLock();        @Override    public void run() {        //模拟卖票        while(true){            //synchronized (lock){
ck.lock(); if (ticket > 0) { //模拟选坐的操作 try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "正在卖票:" + ticket--); } ck.unlock(); //} } }}

 

 

 

二.死锁

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

public class LockA {    private LockA(){}    public final static LockA locka=new LockA();}
public class LockB {    private LockB(){}    public final static LockB lockb=new LockB();}
//线程任务类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++;        }    }}
//测试类public class Demo01 {    public static void main(String[] args) {        DeadLock d1=new DeadLock();        Thread t0=new Thread(d1);        Thread t1=new Thread(d1);        t0.start();        t1.start();    }}

 三.等待唤醒机制

线程之间的通信:多个线程在处理同一个资源,但是处理的动作(线程的任务)却不相同。通过一定的手段使各个线程能有效的利用资源。而这种手段即—— 等待唤醒机制。

等待唤醒机制所涉及到的方法:

①wait() :等待,将正在执行的线程释放其执行资格 和 执行权,并存储到线程池中。

②notify():唤醒,唤醒线程池中被wait()的线程,一次唤醒一个,而且是任意的。

③notifyAll(): 唤醒全部:可以将线程池中的所有wait() 线程都唤醒。

唤醒的意思就是让线程池中的线程具备执行资格。这些方法都是在同步中才有效。同时这些方法在使用时必须标明所属锁,这样才可以明确出这些方法操作的到底是哪个锁上的线程。

这些方法被定义在了Object类中,因为这些方法在使用时,必须要标明所属的锁,而锁又可以是任意对象。能被任意对象调用的方法一定定义在Object类中。

 

如上图说示,输入线程向Resource中输入name ,sex , 输出线程从资源中输出,先要完成的任务是:

1.当input发现Resource中没有数据时,开始输入,输入完成后,叫output来输出。如果发现有数据,就wait();

2.当output发现Resource中没有数据时,就wait() ;当发现有数据时,就输出,然后,叫醒input来输入数据。

//模拟资源类public class Resource {    public String name;    public int age;        public boolean flag;    }
//Input类public class Input implements Runnable{    //对resource进行赋值    private Resource r;    public Input(){}    public Input(Resource r){        this.r=r;    }    public void run() {        int i=0;        while(true){            synchronized (r) {                if(r.flag){                    try {                        r.wait();                    } catch (InterruptedException e) {                        e.printStackTrace();                    }                }                if(i%2==0){                    r.name="张三";                    r.age=18;                }else{                    r.name="lisi";                    r.age=81;                }                r.flag=true;                r.notify();            }            i++;        }    }}
//Output类public class Output implements Runnable{    private Resource r;    public Output(){}    public Output(Resource r){        this.r=r;    }    public void run() {        //对resource输出        while(true){            synchronized (r) {                //判断标记                if(!r.flag){                    try {                        r.wait();                    } catch (InterruptedException e) {                        e.printStackTrace();                    }                }                System.out.println(r.name+"..."+r.age);                r.flag = false;                r.notify();            }        }    }    }
//测试类public class Demo01 {    public static void main(String[] args) {        Resource r=new Resource();        Input in=new Input(r);        Output out=new Output(r);        Thread tin=new Thread(in);        Thread tout=new Thread(out);        tin.start();        tout.start();    }}

 

转载于:https://www.cnblogs.com/akiyama/p/10209253.html

你可能感兴趣的文章
利用Mrjob实现Weighted Slope One算法
查看>>
jmeter旅程第二站:jmeter登录接口测试
查看>>
.Net Core 商城微服务项目系列(六):搭建自己的Nuget包服务器
查看>>
HTML
查看>>
java 多线程
查看>>
细说mysql索引
查看>>
【Linux常用指令整理4】搜索文件
查看>>
zdz工具箱v1.5 android版本发布了,集成各种个人生活中常用的工具,方便日常使用管理...
查看>>
MVC AJAX
查看>>
[SCOI2005]繁忙的都市
查看>>
imx51-linux的cpuinfo之分析
查看>>
elementUI -- table相关的问题
查看>>
WINCE6.0+IMX515通过cfimager.exe烧录镜像文件
查看>>
Day08 数据处理
查看>>
Golang命令行库Cobra的使用
查看>>
centos7下部署Django(nginx+uwsgi+python3+django)
查看>>
集算器协助java处理结构化文本之对齐连接
查看>>
django环境部署-nginx环境
查看>>
android 網易云閱讀 書架的實現
查看>>
day9.初始函数练习题
查看>>