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基础(41)AbstractList类
AbstractList类的子类有AbstractSequentialList(其子类是LinkedList)和ArrayList 1.LinkedList 定义 public class Linke ...
- mysql全局变量和局部变量
全局变量和局部变量 在服务器启动时,会将每个全局变量初始化为其默认值(可以通过命令行或选项文件中指定的选项更改这些默认值).然后服务器还为每个连接的客户端维护一组会话变量,客户端的会话变量在连接时使用 ...
- DP动态规划学习笔记
作为考察范围最广,考察次数最多的算法,当然要开一篇博客来复习啦. 子曰:温故而知新,可以为师矣 我复习DP时有一些自己对DP的理解,也就分享出来吧. ——正片开始—— 动态规划算法,即Dynamic ...
- ArcSDE 10 for SQL Server安装教程(含下载链接)
亲测:ArcSDE 10.1适用于ArcGIS10.2的版本. 该版本支持SQL Server.Oracle.PostgreSQL等数据库连接 下载链接(含安装包和授权文件): 链接:https:// ...
- 学习笔记25_MVC前台API
**当请求url的规则有所改变时,前台的所有超链接的href都得改,为了避免多处修改,可以href = "< %=url.Action("Controller",& ...
- Scrapy爬取豆瓣图书数据并写入MySQL
项目地址 BookSpider 介绍 本篇涉及的内容主要是获取分类下的所有图书数据,并写入MySQL 准备 Python3.6.Scrapy.Twisted.MySQLdb等 演示 代码 一.创建项目 ...
- generator和promise配合解决js异步地狱问题
为何要使用generator函数和promise? js的异步地狱一直是困扰前端程序员的一个头疼的问题 比如说我要获取还有列表,一般来说会使用ajax来获取 $.ajax(...等等,function ...
- 从V神到以太坊——以太坊发展简史
以太坊的出现,让人们的认识从比特币飞跃到了区块链本身.使得区块链技术在非金融领域的普遍应用成为可能,同时,也被认为是区块链2.0时代的标志,是区块链技术发展史上重要的里程碑. 以太坊的故事,要从比特币 ...
- 文字转换为svg动画
将输入文本根据使用字体转化为描边动画. 详情请看git https://oubenruing.github.io/svg-text-animate/
- RocketMQ消息轨迹-设计篇
目录 1.消息轨迹数据格式 2.记录消息轨迹 3.如何存储消息轨迹数据 @(本节目录) RocketMQ消息轨迹主要包含两篇文章:设计篇与源码分析篇,本节将详细介绍RocketMQ消息轨迹-设计相关. ...