Java多线程(2)线程锁
多线程访问同一个资源进行读写操作,就很容易出一些问题(比如我们常见的读者写者,生产者消费者模型)所以我们会选择对他们设置信号量或者加锁,来限制同一个时刻只有一个线程对某个对象进行操作。
多线程是一个蛮复杂的工作,锁加多了就算是看伪代码有的时候脑子都转不过来,所以不要随便加锁(如果对自己的脑子没太多自信的话
Synchronized
Synchronized关键字的作用是实现线程间的同步,它就像我们用PV原语来解决进程互斥问题,然后用对象的wait(),notify()提供线程的同步功能。
它的使用场景如下:
| 分类 | 具体方法 | 被锁的对象 | 伪代码 |
|---|---|---|---|
| 方法 | 实例方法 | 实例对象 | public synchronized void method(){}; //实例方法,锁住的是实例对象 |
| 方法 | 静态方法 | 类对象 | public static synchronized void method(){}; //静态方法,锁住的是类对象 |
| 代码块 | 实例对象 | 类的实例对象 | synchronized(this){...};//同步代码块,锁住的是该类实例对象 |
| 代码块 | class对象 | 类的实例对象 | synchronized(SynchronizedDemo.class){...}; //同步代码块,锁住的是该类的类对象 |
| 代码块 | 任意实例对象Object | 类的实例对象Object | String lock=" "; synchronized(lock){...}; //同步代码块,锁住的是配置的实例对象 |
Attention:如果锁住的是类对象的话,不论new多少个实例出来,因为他们是属于一个类的,所以都会被锁住,保证进程间同步。
从OS的原理上理解,很明显的通过这种方式来依次排队操作共享资源的方式是比较效率低下的。这并不是一个一个非常好的同步机制,但是它是其他并发容器的基础。
Synchronized是怎么实现同步的呢
在学OS的时候,有一章一直在讲PV原语,Proberen申请资源信号量-1,Verhogen释放资源信号量+1(Dijkstra是荷兰人,所以就这么任性的用荷兰语),PV的题目都快做吐了,但是其实在真正的现代OS环境和Java当中,并不是这样简单的来解决问题的。
在Synchronized关键字的机制里面,每个对象拥有一个monitor(计数器),当线程获取该对象锁后,计数器就会加一,释放锁后就会将monitor减一。(为什么你和PV操作刚好相反啊!)
Disadvantage:
由于我们没办法设置synchronized关键字在获取锁的时候等待时间,所以synchronized可能会导致线程为了加锁而无限期地处于阻塞状态。
使用synchronized关键字等同于使用了互斥锁,即其他线程都无法获得锁对象的访问权。这种策略对于读多写少的应用而言是很不利的,因为即使多个读者看似可以并发运行,但他们实际上还是串行的,并将最终导致并发性能的下降。
因为时间片的轮转,导致我们在使用上觉得连贯,在一个时间周期里面看起来像是并发进行(针对单核process而言),但实际上,效率并不高。
Q: Synchronized关键字和lock是一样的吗?它们的区别是什么?
我觉得这两个是不同的概念,但是我的一些同学在开发过程中把Synchronize也叫做锁,一般说加一个对象锁。(虽然觉得不对但是也找不到什么反驳的理由.jpg)
看了一些博客和书之后发现,对象锁知识synchronized在实现锁机制中的一类,它其实有偏向锁,轻量锁,自旋锁等等,所以其实synchronized是一个锁的封装。
关于进程的五状态图这里就不画了,几个状态的切换。值得注意的是,线程在wait()的时候是会释放对象的锁的,而sleep()或者yield()是不会的。
练手的Demo(使用semaphore信号量解决读者写者问题)
https://github.com/JhinQaQ/ReadAndWrite
参考
《Operating Systems : Design and Implementation》
《Java并发编程的艺术》
《实战Java高并发程序设计》
让你彻底理解Synchronized https://www.jianshu.com/p/d53bf830fa09
synchronized的两大不足 http://swiftlet.net/archives/3010
synchronized、锁、多线程同步的原理是咋样的 https://www.jianshu.com/p/5dbb07c8d5d5
Java多线程(2)线程锁的更多相关文章
- Java多线程系列--“JUC锁”03之 公平锁(一)
概要 本章对“公平锁”的获取锁机制进行介绍(本文的公平锁指的是互斥锁的公平锁),内容包括:基本概念ReentrantLock数据结构参考代码获取公平锁(基于JDK1.7.0_40)一. tryAcqu ...
- Java多线程系列--“JUC锁”04之 公平锁(二)
概要 前面一章,我们学习了“公平锁”获取锁的详细流程:这里,我们再来看看“公平锁”释放锁的过程.内容包括:参考代码释放公平锁(基于JDK1.7.0_40) “公平锁”的获取过程请参考“Java多线程系 ...
- Java多线程系列--“JUC锁”10之 CyclicBarrier原理和示例
概要 本章介绍JUC包中的CyclicBarrier锁.内容包括:CyclicBarrier简介CyclicBarrier数据结构CyclicBarrier源码分析(基于JDK1.7.0_40)Cyc ...
- Java多线程系列--“JUC锁”02之 互斥锁ReentrantLock
本章对ReentrantLock包进行基本介绍,这一章主要对ReentrantLock进行概括性的介绍,内容包括:ReentrantLock介绍ReentrantLock函数列表ReentrantLo ...
- Java多线程系列--“JUC锁”01之 框架
本章,我们介绍锁的架构:后面的章节将会对它们逐个进行分析介绍.目录如下:01. Java多线程系列--“JUC锁”01之 框架02. Java多线程系列--“JUC锁”02之 互斥锁Reentrant ...
- Java多线程系列--“JUC锁”09之 CountDownLatch原理和示例
概要 前面对"独占锁"和"共享锁"有了个大致的了解:本章,我们对CountDownLatch进行学习.和ReadWriteLock.ReadLock一样,Cou ...
- Java多线程系列--“JUC锁”06之 Condition条件
概要 前面对JUC包中的锁的原理进行了介绍,本章会JUC中对与锁经常配合使用的Condition进行介绍,内容包括:Condition介绍Condition函数列表Condition示例转载请注明出处 ...
- Java多线程系列--“JUC锁”05之 非公平锁
概要 前面两章分析了"公平锁的获取和释放机制",这一章开始对“非公平锁”的获取锁/释放锁的过程进行分析.内容包括:参考代码获取非公平锁(基于JDK1.7.0_40)释放非公平锁(基 ...
- Java多线程系列--“JUC锁”07之 LockSupport
概述 本章介绍JUC(java.util.concurrent)包中的LockSupport.内容包括:LockSupport介绍LockSupport函数列表LockSupport参考代码(基于JD ...
- Java多线程系列--“JUC锁”08之 共享锁和ReentrantReadWriteLock
概要 Java的JUC(java.util.concurrent)包中的锁包括"独占锁"和"共享锁".在“Java多线程系列--“JUC锁”02之 互斥锁Ree ...
随机推荐
- CentOS 7.3最小系统安装KVM
一.准备工作 安装wget和vim yum install -y wget vim 修改yum源为阿里源 wget -O /etc/yum.repos.d/CentOS-Base.repo http: ...
- Binding的三种方式
1 Text="{Binding Name}" Name为后台的属性 2 Text="{Binding ElementName=XXX,Path=A.B.C.D….}&q ...
- WPF中INotifyPropertyChanged用法与数据绑定
在WPF中进行数据绑定的时候常常会用到INotifyPropertyChanged接口来进行实现,下面来看一个INotifyPropertyChanged的案例. 下面定义一个Person类: usi ...
- Android各版本对应的SDK和JDK版本
原文:Android各版本对应的SDK和JDK版本 一.Android各版本对应的SDK版本: 平台版本 SDK版本 版本名称 Android 8.0 26 Oreo Android 7.1 25 N ...
- C#基础:ref和out的区别 [转]
ref和out的区别在C# 中,既可以通过值也可以通过引用传递参数.通过引用传递参数允许函数成员更改参数的值,并保持该更改.若要通过引用传递参数, 可使用ref或out关键字.ref和out这两个关键 ...
- CentOS搭建python开发环境
装了个CentOS 5.5,想在上面搭个python的开发环境,可是还是遇到了很多问题,记录一下过程: 1.python升级 查看python版本 python -V Python 2.4.3 因为p ...
- Win8 Metro(C#)数字图像处理--2.49Zhang二值图像细化算法
原文:Win8 Metro(C#)数字图像处理--2.49Zhang二值图像细化算法 [函数名称] 二值图像细化算法 WriteableBitmap ThinningProcess ...
- Python爬虫: "追新番"网站资源链接爬取
“追新番”网站 追新番网站提供最新的日剧和日影下载地址,更新比较快. 个人比较喜欢看日剧,因此想着通过爬取该网站,做一个资源地图 可以查看网站到底有哪些日剧,并且随时可以下载. 资源地图 爬取的资源地 ...
- HTML特殊编码转换
var encoded = ""'&<>¡¢£¤" + "¥¦§¨©ª«¬®" + "¯°±²³´µ¶·" ...
- DOTNET CORE DATETIME在LINUX与WINDOWS时间不一致
.net core项目,部署到CentOS上的时候,发现DateTime.Now获取的时间与Windows不一致,主要是时区不一致. static void Main(string[] args) { ...