Java核心复习——synchronized
一、概念
利用锁机制实现线程同步,synchronized关键字的底层交由了JVM通过C++来实现
Java中的锁有两大特性:
- 互斥性
- 同一时间,只允许一个线程持有某个对象锁。
- 可见性
- 锁释放前,线程对变量的修改,后面获得锁的线程可见。
可见性
JMM关于synchronized的两条规定:
线程解锁前,必须把共享变量的最新值刷新到主内存中
线程加锁时,将清空工作内存中共享变量的值,从而使用共享变量时需要从主内存中重新获取最新的值(注意:加锁与解锁需要是同一把锁)
通过以上两点,可以看到synchronized能够实现可见性。
二、用法
synchronized修饰位置与锁的关系:
- 同步方法 —— 对象锁,当前实例对象
- 静态同步方法 —— 类对象锁,当前对象的Class对象
- 同步方法块 —— 对象锁,synchonized括号里配置的对象
public class SynchronizedDemo {
private static int m = 0;
private Object obj = new Object();
/**
* 修饰非静态方法
*/
public synchronized void m1() {
sleep(2);
m++;
}
/**
* 修饰静态方法
*/
public synchronized static void m2() {
sleep(2);
m++;
}
/**
* 同步代码块,对对象加锁
*/
public synchronized void m3() {
synchronized (this) {
sleep(2);
m++;
}
}
public synchronized void m4() {
synchronized (obj) {
sleep(2);
m++;
}
}
/**
* 同步代码块,对类加锁
*/
public synchronized void m5() {
synchronized (SynchronizedDemo.class) {
sleep(2);
m++;
}
}
public static void sleep(int second) {
try {
Thread.sleep(second * 1_000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
三、面试问题
同一个对象在A、B两个线程中分别访问该对象的两个同步方法writer和reader,是否会产生互斥?
class LockDemo{
int a = 0;
public synchronized void writer(){
sleep(10);
a++;
}
public synchronized void reader(){
int i = a;
}
public static void main(String[] args) {
Test test = new Test();
new Thread(() -> {
test.writer();
}).start();
sleep(1);
new Thread(() -> {
test.reader();
}).start();
}
}
答案:会。因为synchronized修饰的是方法,锁是对象锁,默认当前的对象作为锁的对象。只有当A释放锁之后,B才会获得对象的锁。
(1)如果是换成是不同对象呢?
不会互斥,因为锁的是对象,而不是方法。
(2)如果writer、reader方法加上static修饰,两个线程中,类直接调用两个方法呢?
会互斥,因为锁的是Class对象。
(3)如果writer方法用static修饰,reader方法不用呢?
不会互斥。因为一个是对象锁,一个是Class对象锁,锁的类型不同。
Java核心复习——synchronized的更多相关文章
- Java核心复习—— 原子性、有序性与Happens-Before
一. 产生并发Bug的源头 可见性 缓存导致的可见性问题 原子性 线程切换带来的原子性问题 有序性 编译优化带来的有序性问题 上面讲到了 volatile 与可见性,本章再主要讲下原子性.有序性与Ha ...
- Java核心复习——J.U.C AbstractQueuedSynchronizer
第一眼看到AbstractQueuedSynchronizer,通常都会有这几个问题. AbstractQueuedSynchronizer为什么要搞这么一个类? 这个类是干什么的.有什么用? 这个类 ...
- Java核心复习——线程池ThreadPoolExecutor源码分析
一.线程池的介绍 线程池一种性能优化的重要手段.优化点在于创建线程和销毁线程会带来资源和时间上的消耗,而且线程池可以对线程进行管理,则可以减少这种损耗. 使用线程池的好处如下: 降低资源的消耗 提高响 ...
- Java核心复习—— ThreadLocal源码分析
ThreadLocal,叫做线程本地存储,也可以叫做线程本地变量.ThreadLocal为变量在每个线程中都创建了一个副本,那么每个线程可以访问自己内部的副本变量. 一.如何使用 class Acce ...
- Java核心复习 —— J.U.C 并发工具类
一.CountDownLatch 文档描述 A synchronization aid that allows one or more threads to wait until* a set of ...
- Java核心复习—— volatile 与可见性
一.介绍 volatile保证共享变量的"可见性".可见性指的是当一个线程修改变量时,另一个线程能读到这个修改的值. 这里就要提出几个问题. 问题1:为什么一个线程修改时,另一个线 ...
- Java核心复习——CompletableFuture
介绍 JDK1.8引入CompletableFuture类. 使用方法 public class CompletableFutureTest { private static ExecutorServ ...
- Java核心复习——J.U.C LinkedBlockingQueue源码分析
参考文档 LinkedBlockingQueue和ArrayBlockingQueue的异同
- Java核心复习——J.U.C ArrayBlockingQueue源码分析
介绍 依赖关系 源码 构造方法 public ArrayBlockingQueue(int capacity) { this(capacity, false);//默认构造非公平的有界队列 } pub ...
随机推荐
- linux下的缓存机制buffer、cache、swap - 运维总结 ["Cannot allocate memory"问题]
一.缓存机制介绍 在Linux系统中,为了提高文件系统性能,内核利用一部分物理内存分配出缓冲区,用于缓存系统操作和数据文件,当内核收到读写的请求时,内核先去缓存区找是否有请求的数据,有就直接返回,如果 ...
- Go语言中Goroutine的设置
一. 通过runtime包进行多核设置 1.NumCPU()获取当前系统的cpu核数 2.GOMAXPROCS设置当前程序运行时占用的cpu核数 版本1.6之前默认是使用1个核,而之后是全部使用. 好 ...
- 开源框架---tensorflow c++ API 运行第一个“手写字的例子”
#CMakeLists.txt cmake_minimum_required (VERSION ) project (tf_example) set(CMAKE_CXX_FLAGS "${C ...
- 云计算---openstack创建虚拟机过程
虚拟机创建过程: (1)界面或命令行通过RESTful API向keystone获取认证信息.(2)keystone通过用户请求认证信息,并生成auth-token返回给对应的认证请求.(3)界面或 ...
- linux网络编程之socket编程(十一)
今天继续学习socket编程,这次主要是学习超时方法的封装,内容如下: ①.alarm[不常用,了解既可] 它的实现思路是这样的: 但是这种方案有一定的问题,因为闹钟可能会作为其它的用途,这时所设置的 ...
- MyBatis3-topic-01 -安装/下载/官方文档 -执行输入一条已经映射的sql语句
mybatis XML 映射配置文件 (官方文档) -对象工厂(objectFactory) -配置环境(environments) -映射器(mappers) 本地IDEA搭建/测试步骤 创建数据库 ...
- P1080 【NOIP 2012】 国王游戏[贪心+高精度]
题目来源:洛谷 题目描述 恰逢 H国国庆,国王邀请n 位大臣来玩一个有奖游戏.首先,他让每个大臣在左.右手上面分别写下一个整数,国王自己也在左.右手上各写一个整数.然后,让这 n 位大臣排成一排,国王 ...
- async/await中reject的问题
promise 返回的 resolve 对象可能用 await 去接,但是 reject 无法用 await 接收到,所以要用 try catch 去处理 例如发送邮件的接口设置: async fun ...
- /tmp/supervisor.sock no such file 报错
背景: 在执行 supervisorctl 时,报了这么一个错(如图),查找对应文档后解决,记录下来用来以后遇到使用 解决: 1. 将 supervisord.conf 文件下对应的 /tmp 目录 ...
- SVN工作区同步
单击“团队同步”菜单项或“团队同步”视角的“团队”工具栏上的“同步”按钮后,“同步视图”中将显示SVN工作区同步.它提供了从远程检查本地副本的更改类型的概率. 这是“同步视图”中的 “SVN工作空间同 ...