百科狗-知识改变命运!
--

java中Lock的默认Condition问题。

乐乐1年前 (2023-12-23)阅读数 7#综合百科
文章标签线程方法

Lock 替代了synchronized 方法和语句的使用,Condition 替代了Object 监视器方法(wait、notify和notifyAll)的使用。Lock的原理其实和synchronized是一样的。

java的每个对象都有一个监视器,只能被同一线程拥有(即同一线程可重入),一旦被一个线程获取,那其它线程只能等待。synchronized(obj)意思就是获得obj的监视器,对应于monitorenter,代码块结束时自动释放,相当于monitorexit。

只有获得了对象的监视器,才能执行监视器方法,也就是wait、notify或notifyAll。也就是只有synchronized(this)后才能this.wait或this.notify,不能获得一个对象的监视器而执行另一个对象的监视器方法。

在condictin上await后必须有线程调用condition.signal()。你可以在你的线程上提供2个方法:

class RunA implements Runable {

public void wait1() {

lock.lock();

try {

condition.await();

}finally{

lock.unlock();

}

}

public void continue1() {

lock.lock();

try {

condition.signal();

} finally {

lock.unlock();

}

}

}

本线程调用wait1,另一线程调用continue1通知继续,这跟在Object上的wait与notify是一回事

深入理解wait/notify/notifyAll的作用

notify: 唤醒在监视器对象上等待的单个线程,此时调用该方法的代码继续执行。

notifyAll: 唤醒在监视器对象上等待的所有线程,此时调用该方法的代码继续执行。

第一、为什么会有wait/notify/notifyAll这几个方法?

(1) wait/notify/notifyAll是为了避免轮询(尝试执行)带来的性能损失,这句话是什么意思?看下面的讲解:

为了说清道理,我们用“图书馆借书”这个经典例子来作解释。

在简单的synchrnozed 同步机制下,李四如果想借,先要去图书馆查看书有没有还回来。

李四是个心急的人,他每天都去图书馆查;而张三看书看得慢,过了半个月才把书还回来,

结果李四在这半个月里全都白跑了,浪费了不少交通车费。

而如果使用wait/notify机制,李四就不用白忙了。

他第一次去图书馆时发现书已借走,就回家静静等待(wait);

张三把书还掉后,通知(notify)李四,李四去图书馆拿书即可。整个过程中,李四没有白跑,没浪费钱。

书 ---- 临界资源,需互斥地访问

张三,李四 ---- 两个竞争的线程

坐车去图书馆查书 ---- 轮询

车费 ---- CPU空间

等待 ---- wait

通知下一个借书者 ---- notify

也就是说,若使用简单的synchonized机制实现互斥,会导致线程主动发起轮询,若N次轮询没有成功,就产生了N次的CPU空间浪费;

java中Lock的默认Condition问题。

如果加上了 wait/notify机制,就可以避免这些无谓的轮询,节省CPU的消耗。

(2) wait/notify/notifyAll可以控制线程执行与不执行。

第二、为什么wait/notify/notifyAll方法一定要写在synchronized里面呢?

因为第一点已经说了wait/notify/notifyAll的作用是为了避免轮询带来的性能损失,

而产生轮询的条件是多个线程对同一个资源进行操作。

第三、为什么wait/notify/notifyAll方法定义在Object类里面呢?

因为wait/notify/notifyAll必须写在synchronized里面,而synchronized的对象锁可以是任意对象,

所以wait/notify/notifyAll方法定义在Object类里面呢。

调用wait/notify/notifyAll方法的对象,必须和synchronized()的对象锁一致。

第四、

看一个wait和notify示例:

// 这个示例是不需要flag标记的:

public class Resource {

public String name;

public String sex;

public boolean flag = true;

public static void main(String[] args) {

Resource r = new Resource();

Input in = new Input(r);

Thread t1 = new Thread(in);

Output out = new Output(r);

Thread t2 = new Thread(out);

t1.start();

t2.start();

}

}

class Input implements Runnable {

Resource r;

public Input(Resource r) {

this.r = r;

}

public void run() {

int x = 0;

while (true) {

synchronized (r) {

try {

Thread.sleep(1000);

} catch (InterruptedException e1) {

e1.printStackTrace();

}

if (x == 0) {

r.name = "谢霆锋";

r.sex = "男人";

} else {

r.name = "张柏芝";

r.sex = "女人";

}

// 注意:调用notify方法后,唤醒了等待的线程。

// 但这里代码继续执行,并不是马上交给其它线程执行,除非cpu时间片结束。

r.notify();

try {

r.wait();

} catch (InterruptedException e) {

e.printStackTrace();

}

}

x = (x + 1) % 2;

}

}

}

class Output implements Runnable {

Resource r;

public Output(Resource r) {

this.r = r;

}

public void run() {

while (true) {

synchronized (r) {

System.out.println("--------------" + r.name + "是" + r.sex);

r.notify();

try {

r.wait();

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

}

}

--------------------------------------------------------------

这里要注意,再次强调:

wait/notify/notifyAll方法要放在synchronized里面,除此之外,还要非常非常注意一个重点:

调用wait/notify/notifyAll方法的对象,必须要和synchronized的对象锁是一致的。

如,以下代码是错误的:

class MyThread extends Thread {

public static Object obj = new Object();

public void run() {

synchronized(obj) {

try {

this.wait();

} catch (InterruptedException e) {

e.printStackTrace();

}

this.notify();

}

}

}

--------------------------------------------------------------

鹏仔微信 15129739599 鹏仔QQ344225443 鹏仔前端 pjxi.com 共享博客 sharedbk.com

免责声明:我们致力于保护作者版权,注重分享,当前被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理!邮箱:344225443@qq.com)

图片声明:本站部分配图来自网络。本站只作为美观性配图使用,无任何非法侵犯第三方意图,一切解释权归图片著作权方,本站不承担任何责任。如有恶意碰瓷者,必当奉陪到底严惩不贷!

内容声明:本文中引用的各种信息及资料(包括但不限于文字、数据、图表及超链接等)均来源于该信息及资料的相关主体(包括但不限于公司、媒体、协会等机构)的官方网站或公开发表的信息。部分内容参考包括:(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供参考使用,不准确地方联系删除处理!本站为非盈利性质站点,本着为中国教育事业出一份力,发布内容不收取任何费用也不接任何广告!)