Java并发之synchronized关键字和Lock接口
欢迎点赞阅读,一同学习交流,有疑问请留言 。
GitHub上也有开源 JavaHouse,欢迎star
引用
当开发过程中,我们遇到并发问题。怎么解决?
一种解决方式,简单粗暴:上锁。将千军万马都给拦下来,只允许一个人过独木桥。书面意思就是将并行的程序变成串行的程序。现实的锁有门锁、挂锁和抽屉锁等等。在Java中,我们的锁就是synchronized关键字和Lock接口。
synchronized关键字
synchronized也叫同步锁,是Java里面的关键字。我们可以猜测到synchronized原理也JVM虚拟机有关联。
synchronized锁的是对象。对象里面有一个叫做监视锁(monitor)的东西,监视锁依赖操作系统的互斥锁(Mutex Lock)。操作系统切换线程其实就是从用户态编程核心态(cpu的两种状态)。这个代价有点高,所以synchronized这个重量级锁后面也引进了偏向锁和轻量级锁。
加锁(监视锁monitor)过程分析():
- 当monitor的进入数为0,线程A进入
- monitor的进入数为1
- 线程B想进入该monitor就会被阻塞。
线程A可以重复进入该monitor,所以synchronized是可重入锁,和Lock实现的锁一样。
- 程序验证
public class SynchronizedTest {
private static int i = 0;
public static void main(String[] args) {
test();
}
public static void test(){
synchronized (SynchronizedTest.class){
synchronized (SynchronizedTest.class){
i++;
}
}
}
}
- 运行结果
程序正常运行,没有报错
synchronized可以修饰方法以及代码块,代码块就是上面重入锁的例子。
- 修饰方法
public class SynchronizedTest {
static int n = 100;
final static CountDownLatch start = new CountDownLatch(n);
private static int i = 0;
public static void main(String[] args) throws InterruptedException {
for (int j = 0; j < n; j++) {
Thread thread = new Thread(new addNoSynchronized());
thread.start();
}
start.await();
System.out.println(i);
}
public static class addSynchronized implements Runnable{
@Override
public void run() {
addSynchronized();
}
public static synchronized void addSynchronized(){
for (int j = 0; j < 1000; j++) {
i++;
}
start.countDown();
}
}
}
- 运行结果
100000
如果去掉 synchronized 关键字的话,运行结果大概率不是 100000,因为线程不安全问题。
Lock接口
一般我们使用 ReentrantLock 类作为重入锁,实现Lock接口。
- 使用方法
public class ReentranLockTest {
private static int j;
private static int n = 100;
private static CountDownLatch latch = new CountDownLatch(n);
public static void main(String[] args) throws InterruptedException {
for (int i = 0; i < n; i++) {
new Thread(new LockTest()).start();
}
latch.await();
System.out.println("结果为:"+j);
}
public static class LockTest implements Runnable{
static Lock lock = new ReentrantLock();
@Override
public void run() {
lockTest();
latch.countDown();
}
private void lockTest() {
lock.lock();
try {
for (int i = 0; i < 1000; i++) {
j++;
}
}finally {
lock.unlock();
}
}
}
}
- 运行结果
结果为:100000
这里我们锁住的 j++ 这块资源区(公共资源),lock 是 static 关键字修饰的,是类对象,思考一下如果不是类对象会怎么样?那就是连环锁了(看图)。

每一个线程都对可以用钥匙解开这把锁,对于程序而言,加锁操作就没有意义了。因为我们需要的是一个锁。
欢迎关注我的微信公众号

Java并发之synchronized关键字和Lock接口的更多相关文章
- Java并发之synchronized关键字深度解析(二)
前言 本文继续[Java并发之synchronized关键字深度解析(一)]一文而来,着重介绍synchronized几种锁的特性. 一.对象头结构及锁状态标识 synchronized关键字是如何实 ...
- synchronized关键字,Lock接口以及可重入锁ReentrantLock
多线程环境下,必须考虑线程同步的问题,这是因为多个线程同时访问变量或者资源时会有线程争用,比如A线程读取了一个变量,B线程也读取了这个变量,然后他们同时对这个变量做了修改,写回到内存中,由于是同时做修 ...
- Java多线程:synchronized关键字和Lock
一.synchronized synchronized关键字可以用于声明方法,也可以用来声明代码块,下面分别看一下具体的场景(摘抄自<大型网站系统与Java中间件实践>) 案例一:其中fo ...
- Java并发之synchronized关键字深度解析(一)
前言 近期研读路神之绝世武学,徜徉于浩瀚无垠知识之海洋,偶有攫取吉光片羽,惶恐未领略其精髓即隐入岁月深处,遂急忙记录一二,顺备来日吹cow之谈资.本小系列为并发之亲儿子-独臂狂侠synchronize ...
- 线程中synchronized关键字和lock接口的异同
一.synchronized关键字 1.可以用来修饰代码块 synchronized (this) { // 同步的关键字 this 表示当前线程对象 if (num == 0) { break; } ...
- Java并发之synchronized关键字
上篇文章我们主要介绍了并发的基本思想以及线程的基本知识,通过多线程我们可以实现对计算机资源的充分利用,但是在最后我们也说明了多线程给程序带来的两种典型的问题,针对它们,synchronize ...
- Java并发之synchronized关键字深度解析(三)
前言 本篇主要介绍一下synchronized的批量重偏向和批量撤销机制,属于深水区,大家提前备好氧气瓶. 上一篇说完synchronized锁的膨胀过程,下面我们再延伸一下synchronized锁 ...
- 深入理解Java并发之synchronized实现原理
深入理解Java类型信息(Class对象)与反射机制 深入理解Java枚举类型(enum) 深入理解Java注解类型(@Annotation) 深入理解Java类加载器(ClassLoader) 深入 ...
- 并发之synchronized关键字的应用
并发之synchronized关键字的应用 synchronized关键字理论基础 前两章我们学习了下java内存模型的相关知识, 现在我们来讲讲逢并发必出现的synchronized关键字. 作用 ...
随机推荐
- Java自动化测试框架-08 - TestNG之并行性和超时篇 (详细教程)
一.并行性和超时 您可以指示TestNG以各种方式在单独的线程中运行测试. 可以通过在suite标签中使用 parallel 属性来让测试方法运行在不同的线程中.这个属性可以带有如下这样的值: 二.并 ...
- 知否知否,VS Code 不止开源
VS Code, 昨夜始于“开源”,如今“开源”深处渡. 读者看到这句话,也许会有疑惑,为什么两个“开源”都加上了双引号? 其实是笔者有意为之,因为这个两个“开源”的意义有着很大的差别,第一个“开源” ...
- 学习笔记31_ORM框架ModelFirst设计数据库
ModelFirst就是先设计实体数据类型,然后根据设计的数据类型,生成数据库表 1.新建项--ADO.NET实体数据模型--空数据模型--进入模型设计器(点击xxx.edmx文件也能进入设计器). ...
- [考试反思]1024csp-s模拟测试85:以为
愈发垃圾. T1基本全场切(除了RP<-inf的zkt和把人擦) 然后T2想了半天逐渐趋近于正解,但是因为数据有问题锅了25分,没什么好说的.T3连题意转化都没有完成.括号匹配转为+1/-1做法 ...
- NOIP模拟 34
次芝麻,喝喝喝,长寿花! 什么鬼畜题面...一看就不是什么正经出题人 skyh双双双AK了..太巨了... T1 次芝麻 稍稍手玩就能发现分界点以一个优美的方式跳动 然后就愉快地帮次货们次掉了这个题- ...
- STL库学习笔记(一)——什么是STL?
小明是一个很牛逼的程序员,在国际标准化组织工作. 他现在正在设计新一代的C++标准,标准中有一个待实现的函数:findMax(),这个函数要求使用者输入任何类型的数据,他都能找到最大的一个. 于是他想 ...
- php debug_backtrace方法跟踪代码调用
php debug_backtrace方法跟踪代码调用<pre>function string 当前的函数名,参见: __FUNCTION__.line integer 当前的行号.参见: ...
- jquery判断手指滑动方向
jquery判断手指滑动方向 <pre> /*判断哪个滑动方向还是自己改下 要么上下 要么左右*/ var startX; var startY; $(".shanghua&qu ...
- jquery设置html5音量的方法
jquery设置html5音量的方法<pre> setTimeout(function() { alert(1); $('#music1')[0].volume = 0; setTimeo ...
- php nginx反向代理获取真实ip的教程
php nginx反向代理获取真实ip的教程 <pre> location /getip { proxy_pass http://newmiracle.cn/ip.php; } proxy ...