实践46
同步机制锁定的是对象,而不是函数或代码。当synchronized被当作函数修饰符时,它所取得的lock被交给函数的调用者。如果synchronized用于object reference,则取得的lock交给该reference所指的对象。(因此同一类2个不同对象之间加this锁是无效的,因为不是同一个锁)
Java不允许将构造函数声明为synchronized。当两个线程并发调用一个构造函数的时候,它们各自操控的是同一个class的两个不同实体的内存。但如果构造函数内部包含竞争共享资源的代码,则必须同步控制以回避冲突。
实践47
当调用一个synchronized static函数时,获得的lock将与[定义该函数]之class的Class对象相关联,而不是与调用函数的那个对象相关联。当对一个class literal调用其synchronized 区段时,获得的也是同样那个lock,也就是[与特定Class 对象相关联]的lock
看一段代码:
class Foo implements Runnable{
public synchronized void printM1(){
while(true)
System.out.println("M1");
}
public synchronized static void printM2(){
while(true)
System.out.println("M2");
}
public void run(){
printM1();
}
}
class Test{
public static void main(String args[]){
Foo f=new Foo();
Thread t=new Thread(f);
t.start();
f.printM2;
}
}
这段代码最终较差打印了M1和M2 而没有实现同步
原因在于:一个同步的是static函数,而一个是instance函数,printM1取得的是Foo object lock,而printM2取得的则是Foo的Class object lock。
要使上述代码同步可以:1 同步控制公共资源 2 同步控制一个特殊的instance变量
用byte[] lock=new byte[0];是最经济的
实践48
对于[在synchronized函数中可被修改的数据],应使之成为private,并根据需要提供访问函数。如果访问函数返回的是可变对象(mutable object),那么应该先cloned(克隆)该对象。
实践49
一般情况下请不要同步化所有函数,同步化不仅造成程序缓慢,并且丧失了并发可能
采用“单对象多锁”技术以允许更多并发动作。
实践50
不可分割的操作并不意味着多线程安全。只要多个线程共享某些变量,它们就必须被访问于synchronized函数或区段内,或是被声明为volatile。这样可以确保变量与主内存完全保持一致,从而在任何时刻都得到正确数值。
采用synchronized或是volatile取决于多个因素。如果并发性很红药,且不需要更新很多变量,可以使用volatile,如果要更新许多变量,volatile执行速度会比同步低。如果使用synchronized,只有在取得和释放lock的时候,变量和主内存才进行一致化
两者关系:
synchronized
优点:取得和释放lock时进行私有专用副本和主内存正本的一致化
缺点:清除了并发性的可能
volatile
优点:允许并发性
缺点:每次访问变量就会进行私有专用内存对应主内存的一致化
实践51
同步化某一函数,并不一定就会使其成为“多线程安全”,如果synchronized函数操控着多个函数,而它们并不都是此函数所属class的private instance data,那么你必须对这些对象自身也进行同步化。
对关键词synchronized必须记住,它锁定的是对象而非函数或代码。
实践52
以固定而全局性的顺序取得多个locks(机锁)以避免死锁
实践53
优先使用notifyAll()而非notify()
notify()只唤醒一个线程 而你无法控制唤醒哪一个线程 只有在2个前提下 用notify才是安全的:
1 只有一个线程在等待
2 多个线程正等待同一条件成立,且哪个被唤醒都无所谓
线程式的优先权(priority)不能确保线程一定被notify()唤醒,也不能确定各线程被notifyAll()以何种顺序唤醒。
实践54
针对wait()和notifyAll()使用旋锁(spin locks)
由于被唤醒的线程会从之前调用wait()的地点开始继续向下执行,英雌在等待条件变量时,请总是使用旋锁确保正确结果。如下:
if(condition==true){
try{
a.wait()
}catch(){}
}
改成
while(condition==true){
try{
a.wait()
}catch(){}
}
从而保证唤醒后条件仍然成立没有被改变
实践55
使用wait(),notifyAll()代替轮询
实践56
当一个对象被锁定,有可能其他线程会因同一个object lock而受阻(blocked),假如你对上锁对象的object reference重新赋值,其他线程内悬而未决的那些locks将不再有意义。
所以,不要对上锁对象的object reference重新赋值
实践57
不要调用stop()和suspend()方法
实践58
通过线程间协作来终止线程
private volatile boolean stop;
public void stopThread(){
stop=true;
}
public void run(){
while(!stop){}
//do Clean Works...
}
很可惜这里必须用到轮询 并且注意stop变量被声明为volatile以确保值永远是最新的
分享到:
相关推荐
6. **多线程**:线程的创建、同步与通信,如synchronized关键字、wait()、notify()方法和并发工具类。 7. **设计模式**:常见的设计模式如单例、工厂、观察者、装饰器、代理等,以及它们在实际开发中的应用。 8. *...
38 -设备部经理绩效考核表1
在做了充分的需求分析之后,将一站式电脑配件交易平台的需求分为商品管理、订单管理、配送管理、组装管理和评论管理等多个子模块,随后对系统进行设计,设计主要从系统整体架构和数据库两方面进行分析和设计,系统的核心功能主要包括商品管理、订单管理、配送管理、组装管理和评论管理,而非核心功能主要包含了用户管理和用户登录管理等模块。而后,对系统进行了编码并实现了所有功能,最后,对系统相关功能展开测试,并通过了系统测试,充分验证了系统可用性。
数据名称:2000-2022年各县市区主要社会经济发展指标面板数据 数据类型:dta格式 数据来源:中国县域统计
内容概要:本文提供了针对大学生英语竞赛写作准备的重要资源——一系列通用的英文句子模板。这些模板涵盖了现代经济社会的各种话题,从科技进步到环境保护,以及个人品质和社会责任等,并且适用于论述类文章、观点对比和个人见解的表达。文章通过对每一句话的应用环境解释和语法提示,确保使用者可以在实际写作中正确且有效地应用这些表达方式。 适合人群:正在准备参加大学生英语竞赛的学生及其他希望提高书面表达能力的学习者。 使用场景及目标:考生能够在竞赛时间内迅速构建思路完整的文章,增强语言表达的流利性和规范性;帮助学习者积累高级词汇,提升英语写作水平并培养良好的思维逻辑。 阅读建议:结合历年优秀范文进行深入学习,熟悉不同类型话题下的表述方法;练习将提供的句子融入自身创作的文章中,通过不断修订和完善来巩固记忆。同时也可以用于日常的英语写作训练当中。
本代码参考网络大神代码以及结合自身理解,编写的关于使用STM32F103C8T6芯片,通过ESP8266模块,连接阿里云物联网平台的代码历程,文件内包含了如何修改代码连接自己的设备的教程(readme.txt)文件,请读者仔细阅读。
宽带折叠传输阵天线.pdf
这是一个exe程序,解压后可以批量将Word文件转为PDF文件。
09 -单证部经理绩效考核表1
2009-2022年农村金融发展水平省级面板数据 31省份金融发展水平数据(不含港澳台地区) 涉农贷款金额亿元/第一产业增加值 30省份第一产业产值(2009-2022年) 30省份农业金融发展水平(2009-2022年)
2022年9月全国大学生英语竞赛A类初赛参考答案
Python源码03之解决对图片格式进行批量转换的问题.zip
病毒
基于向量特征的车辆轨迹预测.pdf
10-15-物控人员绩效考核表(自动计算、等级评价、任意设置)
员工末位淘汰考评表
1、操作简单,导入(待分班的数据xlsx格式),分班、导出三步。 2、分班条件设置:可选科类组合,设置起始班级和学生预设班级。 3、分班结果:班级人数均衡、男女均衡,各科成绩和总分班级均衡,最大分差不超过0.5分。 4、导出xlsx格式的分班结果。含各班单独的工作表和统计数据表。
人事档案登记及查询系统
第3课《安塞腰鼓》课件-语文八年级下册
C语言之考勤模拟系统平台(千行代码)