多线程访问同一个资源进行读写操作,就很容易出一些问题(比如我们常见的读者写者,生产者消费者模型)所以我们会选择对他们设置信号量或者加锁,来限制同一个时刻只有一个线程对某个对象进行操作。

多线程是一个蛮复杂的工作,锁加多了就算是看伪代码有的时候脑子都转不过来,所以不要随便加锁(如果对自己的脑子没太多自信的话

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)线程锁的更多相关文章

  1. Java多线程系列--“JUC锁”03之 公平锁(一)

    概要 本章对“公平锁”的获取锁机制进行介绍(本文的公平锁指的是互斥锁的公平锁),内容包括:基本概念ReentrantLock数据结构参考代码获取公平锁(基于JDK1.7.0_40)一. tryAcqu ...

  2. Java多线程系列--“JUC锁”04之 公平锁(二)

    概要 前面一章,我们学习了“公平锁”获取锁的详细流程:这里,我们再来看看“公平锁”释放锁的过程.内容包括:参考代码释放公平锁(基于JDK1.7.0_40) “公平锁”的获取过程请参考“Java多线程系 ...

  3. Java多线程系列--“JUC锁”10之 CyclicBarrier原理和示例

    概要 本章介绍JUC包中的CyclicBarrier锁.内容包括:CyclicBarrier简介CyclicBarrier数据结构CyclicBarrier源码分析(基于JDK1.7.0_40)Cyc ...

  4. Java多线程系列--“JUC锁”02之 互斥锁ReentrantLock

    本章对ReentrantLock包进行基本介绍,这一章主要对ReentrantLock进行概括性的介绍,内容包括:ReentrantLock介绍ReentrantLock函数列表ReentrantLo ...

  5. Java多线程系列--“JUC锁”01之 框架

    本章,我们介绍锁的架构:后面的章节将会对它们逐个进行分析介绍.目录如下:01. Java多线程系列--“JUC锁”01之 框架02. Java多线程系列--“JUC锁”02之 互斥锁Reentrant ...

  6. Java多线程系列--“JUC锁”09之 CountDownLatch原理和示例

    概要 前面对"独占锁"和"共享锁"有了个大致的了解:本章,我们对CountDownLatch进行学习.和ReadWriteLock.ReadLock一样,Cou ...

  7. Java多线程系列--“JUC锁”06之 Condition条件

    概要 前面对JUC包中的锁的原理进行了介绍,本章会JUC中对与锁经常配合使用的Condition进行介绍,内容包括:Condition介绍Condition函数列表Condition示例转载请注明出处 ...

  8. Java多线程系列--“JUC锁”05之 非公平锁

    概要 前面两章分析了"公平锁的获取和释放机制",这一章开始对“非公平锁”的获取锁/释放锁的过程进行分析.内容包括:参考代码获取非公平锁(基于JDK1.7.0_40)释放非公平锁(基 ...

  9. Java多线程系列--“JUC锁”07之 LockSupport

    概述 本章介绍JUC(java.util.concurrent)包中的LockSupport.内容包括:LockSupport介绍LockSupport函数列表LockSupport参考代码(基于JD ...

  10. Java多线程系列--“JUC锁”08之 共享锁和ReentrantReadWriteLock

    概要 Java的JUC(java.util.concurrent)包中的锁包括"独占锁"和"共享锁".在“Java多线程系列--“JUC锁”02之 互斥锁Ree ...

随机推荐

  1. 自由度(degree of freedom)

    In many scientific fields, the degrees of freedom of a system is the number of parameters of the sys ...

  2. Nginx http filter异常排查

    问题: 访问异常 root@cloud:/usr/local/nginx# curl -i http://localhost/test.html curl: (52) Empty reply from ...

  3. 关闭Mac OS 的Rootless

    今天在使用mac的时候,需要删除 /usr/bin/下的 自带的php文件.然后提示Operation not permitted 使用sudo 依然不可以,通过google 得到解决方案. 需要关闭 ...

  4. AngularJS ng-if使用

    示例中,根据ng-if指令显示不同任务状态,以及判断任务是否可以操作 <div ng-app="NgifDemoApp" ng-controller="NgifDe ...

  5. WPF编游戏系列 之三 物品清单

    原文:WPF编游戏系列 之三 物品清单        本篇将介绍如何通过C#自动生成游戏界面,主要演示点击"My Shop"后如何显示所有物品清单.其中数据源来自于Access 2 ...

  6. C#/WPF 计算字串的真实长度,调整控件的宽度

    下面函数是经常用到的计算字串长度的方法:         private double MeasureTextWidth(String str, string fontName, double fon ...

  7. 备份一个支持虚拟化的wrappanel

    public class VirtualizingWrapPanel : VirtualizingPanel, IScrollInfo { #region Fields UIElementCollec ...

  8. Win8 Metro(C#)数字图像处理--2.39二值图像投影

    原文:Win8 Metro(C#)数字图像处理--2.39二值图像投影  [函数名称]   二值图像投影         ImageProjection(WriteableBitmap src) ...

  9. GitLab一键式安装bitnami 专题

    git lab developer角色不能提交到master分支的问题 错误提示: git -c diff.mnemonicprefix=false -c core.quotepath=false p ...

  10. 跨进程访问VCL的一个用例(Delphi6、TurboDelphi测试通过)

    Controls.pas单元中有一个FindControl函数,通过句柄获得对应的TWinControl对象. function FindControl(Handle: HWnd): TWinCont ...