当前位置: 首页 > news >正文

IT题库7-线程加锁

转载:http://www.cnblogs.com/linjiqin/p/3208843.html

一、同步问题提出

线程的同步是为了防止多个线程访问一个数据对象时,对数据造成的破坏。
例如:两个线程ThreadA、ThreadB都操作同一个对象Foo对象,并修改Foo对象上的数据。

二、同步和锁定

1、锁的原理
Java中每个对象都有一个内置锁。

当程序运行到非静态的synchronized同步方法上时,自动获得与正在执行代码类的当前实例(this实例)有关的锁。获得一个对象的锁也称为获取锁、锁定对象、在对象上锁定或在对象上同步。

当程序运行到synchronized同步方法或代码块时该对象锁才起作用。

一个对象只有一个锁。所以,如果一个线程获得该锁,就没有其他线程可以获得锁,直到第一个线程释放(或返回)锁。这也意味着任何其他线程都不能进入该对象上的synchronized方法或代码块,直到该锁被释放。

释放锁是指持锁线程退出了synchronized同步方法或代码块。

关于锁和同步,有一下几个要点:
1)、只能同步方法,而不能同步变量和类;
2)、每个对象只有一个锁;当提到同步时,应该清楚在什么上同步?也就是说,在哪个对象上同步?
3)、不必同步类中所有的方法,类可以同时拥有同步和非同步方法。
4)、如果两个线程要执行一个类中的synchronized方法,并且两个线程使用相同的实例来调用方法,那么一次只能有一个线程能够执行方法,另一个需要等待,直到锁被释放。也就是说:如果一个线程在对象上获得一个锁,就没有任何其他线程可以进入(该对象的)类中的任何一个同步方法。
5)、如果线程拥有同步和非同步方法,则非同步方法可以被多个线程自由访问而不受锁的限制。
6)、线程睡眠时,它所持的任何锁都不会释放。
7)、线程可以获得多个锁。比如,在一个对象的同步方法里面调用另外一个对象的同步方法,则获取了两个对象的同步锁。
8)、同步损害并发性,应该尽可能缩小同步范围。同步不但可以同步整个方法,还可以同步方法中一部分代码块。
9)、在使用同步代码块时候,应该指定在哪个对象上同步,也就是说要获取哪个对象的锁。例如:

当然,同步方法也可以改写为非同步方法,但功能完全一样的,例如:
public synchronized int getX() {
      return x++;
}

public int getX() {
      synchronized (this) {
            return x++;
      }
}
效果是完全一样的。

 

二、静态方法同步
要同步静态方法,需要一个用于整个类对象的锁,这个对象就是这个类(XXX.class)。
例如:
public static synchronized int setName(String name){
      Xxx.name = name;
}
等价于
public static int setName(String name){
      synchronized(Xxx.class){
            Xxx.name = name;
      }
}

 

四、如果线程不能获得锁会怎么样
如果线程试图进入同步方法,而其锁已经被占用,则线程在该对象上被阻塞。实质上,线程进入该对象的的一种池中,必须在哪里等待,直到其锁被释放,该线程再次变为可运行或运行为止。

当考虑阻塞时,一定要注意哪个对象正被用于锁定:
1、调用同一个对象中非静态同步方法的线程将彼此阻塞。如果是不同对象,则每个线程有自己的对象的锁,线程间彼此互不干预。
2、调用同一个类中的静态同步方法的线程将彼此阻塞,它们都是锁定在相同的Class对象上。
3、静态同步方法和非静态同步方法将永远不会彼此阻塞,因为静态方法锁定在Class对象上,非静态方法锁定在该类的对象上。
4、对于同步代码块,要看清楚什么对象已经用于锁定(synchronized后面括号的内容)。在同一个对象上进行同步的线程将彼此阻塞,在不同对象上锁定的线程将永远不会彼此阻塞。

 

五、何时需要同步
在多个线程同时访问互斥(可交换)数据时,应该同步以保护数据,确保两个线程不会同时修改更改它。

对于非静态字段中可更改的数据,通常使用非静态方法访问。
对于静态字段中可更改的数据,通常使用静态方法访问。

 

六、线程安全类
当一个类已经很好的同步以保护它的数据时,这个类就称为“线程安全的”。

 

七、线程死锁
死锁对Java程序来说,是很复杂的,也很难发现问题。当两个线程被阻塞,每个线程在等待另一个线程时就发生死锁。

 

八、线程同步小结

1、线程同步的目的是为了保护多个线程访问一个资源时对资源的破坏。
2、线程同步方法是通过锁来实现,每个对象都有切仅有一个锁,这个锁与一个特定的对象关联,线程一旦获取了对象锁,其他访问该对象的线程就无法再访问该对象的其他同步方法。
3、对于静态同步方法,锁是针对这个类的,锁对象是该类的Class对象。静态和非静态方法的锁互不干预。一个线程获得锁,当在一个同步方法中访问另外对象上的同步方法时,会获取这两个对象锁。
4、对于同步,要时刻清醒在哪个对象上同步,这是关键。
5、编写线程安全的类,需要时刻注意对多个线程竞争访问资源的逻辑和安全做出正确的判断,对“原子”操作做出分析,并保证原子操作期间别的线程无法访问竞争资源。
6、当多个线程等待一个对象锁时,没有获取到锁的线程将发生阻塞。
7、死锁是线程间相互等待锁锁造成的,在实际中发生的概率非常的小。真让你写个死锁程序,不一定好使,呵呵。但是,一旦程序发生死锁,程序将死掉。

 

转载:http://www.cnblogs.com/linjiqin/p/3208843.html

转载于:https://www.cnblogs.com/sikewang/p/9628744.html

相关文章:

  • sysbench使用
  • CSS.2
  • 程序架构探讨—002 应用服务器集群的伸缩性之负载均衡
  • Web安全系列(二):XSS 攻击进阶(初探 XSS Payload)
  • 3点建议:如何在面试中回答“你最大的成就”
  • 简单的node爬虫练手,循环中的异步转同步
  • 活跃银行×××之二:创新的恶意软件Osiris
  • “数据中心运维管理VIP学习群”问题汇总(一)
  • Oracle 数据文件及其管理
  • Oh!MongoDB日志从文本穿越成了图片?咋整!
  • AtCoder Grant Contest 10.F 博弈
  • Centos7安装Openresty和orange
  • 在ubuntu18实践
  • 非常全面的vim配置文件
  • EXCHANGE DAG环境如何排除ISCSI使用的网络适配器
  • 【从零开始安装kubernetes-1.7.3】2.flannel、docker以及Harbor的配置以及作用
  • ECMAScript入门(七)--Module语法
  • java8 Stream Pipelines 浅析
  • JavaScript中的对象个人分享
  • java小心机(3)| 浅析finalize()
  • opencv python Meanshift 和 Camshift
  • Perseus-BERT——业内性能极致优化的BERT训练方案
  • React的组件模式
  • SpriteKit 技巧之添加背景图片
  • vue-loader 源码解析系列之 selector
  • 干货 | 以太坊Mist负责人教你建立无服务器应用
  • 互联网大裁员:Java程序员失工作,焉知不能进ali?
  • 力扣(LeetCode)357
  • 批量截取pdf文件
  • 前端临床手札——文件上传
  • 前端之React实战:创建跨平台的项目架构
  • 区块链共识机制优缺点对比都是什么
  • 如何将自己的网站分享到QQ空间,微信,微博等等
  • 译有关态射的一切
  • ​Base64转换成图片,android studio build乱码,找不到okio.ByteString接腾讯人脸识别
  • ​Linux·i2c驱动架构​
  • # C++之functional库用法整理
  • (Redis使用系列) Springboot 使用redis实现接口Api限流 十
  • (二)Pytorch快速搭建神经网络模型实现气温预测回归(代码+详细注解)
  • (附源码)springboot宠物医疗服务网站 毕业设计688413
  • (附源码)springboot高校宿舍交电费系统 毕业设计031552
  • (机器学习-深度学习快速入门)第一章第一节:Python环境和数据分析
  • (免费领源码)python#django#mysql公交线路查询系统85021- 计算机毕业设计项目选题推荐
  • (三) prometheus + grafana + alertmanager 配置Redis监控
  • (十二)python网络爬虫(理论+实战)——实战:使用BeautfulSoup解析baidu热搜新闻数据
  • (十三)Maven插件解析运行机制
  • (转)Linq学习笔记
  • (转)创业家杂志:UCWEB天使第一步
  • .NET 6 Mysql Canal (CDC 增量同步,捕获变更数据) 案例版
  • .Net 中的反射(动态创建类型实例) - Part.4(转自http://www.tracefact.net/CLR-and-Framework/Reflection-Part4.aspx)...
  • .NET单元测试
  • .pyc文件是什么?
  • [ Linux ] Linux信号概述 信号的产生
  • [AMQP Connection 127.0.0.1:5672] An unexpected connection driver error occured
  • [BZOJ] 2044: 三维导弹拦截