synchronized 是什么?
老王:小陈,从今天开始我们就要进入synchronized的讨论了;首先小陈你来讲讲对synchronized的理解
小陈:synchronized啊,我理解就是一个JDK提供的同步的关键字,通过synchronized可以锁定一个代码块或者一个方法,从而实现锁的效果。
通过synchronized锁定的代码块或者方法同一时间只能由一个线程去执行,等这个线程执行完了释放锁了之后别的线程才能获取锁进入并且执行。
老王:那你说说synchronized的几种用法?
小陈:嘿嘿,这还不简单
synchronized的几种用法
(1)修饰在对象方法上:
代码语言:javascript复制public class SynDemo {
int i = 0;
int x = 0;
public synchronized void testSync() {
i ;
x ;
}
}
放在实例方法上的时候,锁住的是这个SyncDemo的实例对象。
(2)修饰在静态方法上:
代码语言:javascript复制public class SynDemo {
static int value = 0;
public synchronized static void testStaticSync() {
value ;
}
}
修饰在静态方法上的时候,锁的是这个类对应的类对象,也就是SyncDemo.class对象
(3)在方法内部的同步代码块:
代码语言:javascript复制public class SynDemo {
int i = 0;
int x = 0;
Object lockObj = new Object();
public void testInnerSync() {
synchronized(lockObj) {
i ;
x ;
}
}
}
像这种方式,锁住其实就是lockObj这个对象。
小陈:老王,synchronized使用的三种方式我讲完了
synchronized注意事项
老王:既然你都知道使用的几种方式了,那么使用synchronized关键字需要注意的是什么?
小陈:其实synchronized是对一个对象上锁的,使用的时候需要注意在对同一个对象上锁才能达到互斥的目的。
我直接上代码来讲解一下吧:
(1)定义一个TestThread类,继承自Thread
(2)TestThread的内部持有一个SycDemo对象
(3)TestThread的run方法内部调用SyncDemo对象的testSync方法执行synchronized修饰的同步方法。
代码语言:javascript复制public class SynDemo {
int i = 0;
int x = 0;
// 争抢对象SyncDemo的锁
public synchronized void testSync() {
i ;
x ;
}
static class TestThread extends Thread {
SynDemo lock;
TestThread(SynDemo lock) {
this.lock = lock;
}
@Override
public void run() {
lock.testSync();
}
}
public static void main(String[] args) {
// 锁对象lock1
SynDemo lock1 = new SynDemo();
// 锁对象lock2
SynDemo lock2 = new SynDemo();
TestThread threadA = new TestThread(lock1);
TestThread threadB = new TestThread(lock2);
threadA.start();
threadB.start();
}
}
像这种方式,threadA和threadB是达不到互斥的目的的,因为threadA锁住的是lock1对象;然而thread锁住的是lock2对象。完全争抢的不是同一个锁。
老王:那如果要使得threadA和threadB达到同步的目的,应该怎么做?
小陈:需要threadA和threadB争抢同一把锁,争抢同一个同一个对象的锁才可以,也就是像下面那样,也就是threadA和threadB都使用同一对象锁ock1,这样才是正确的:
代码语言:javascript复制public static void main(String[] args) {
// 只有一个锁对象lock1
SynDemo lock1 = new SynDemo();
// 两个线程对同一个对象锁进行争抢
TestThread threadA = new TestThread(lock1);
TestThread threadB = new TestThread(lock1);
threadA.start();
threadB.start();
}
小陈:对于synchronized修饰static的方法,synchronized锁的是这个类对象,由于类对象只有一个,所以不同线程同时通过类调用这个方法的时候就能互斥的效果。
老王:嗯嗯,看来synchronized的使用方式、注意事项你都基本理解了;下面我们就来深入一点,开始探索synchronized的底层的实现原理了....
小陈:嘿嘿,终于可以进入原理级别去理解synchronized了......
老王:下一篇 《对象头、Mark Word、monitor、synchronized怎么关联起来?》 你别错过哦....
小陈:好的,老王,我们下一章见。
目录
JAVA并发专题 《筑基篇》
1.什么是CPU多级缓存模型?
2.什么是JAVA内存模型?
3.线程安全之可见性、有序性、原子性是什么?
4.什么是MESI缓存一致性协议?怎么解决并发的可见性问题?
JAVA并发专题《练气篇》
5.volatile怎么保证可见性?
6.什么是内存屏障?具有什么作用?
7.volatile怎么通过内存屏障保证可见性和有序性?
8.volatile为啥不能保证原子性?
9.synchronized是个啥东西?应该怎么使用?
10.synchronized底层之monitor、对象头、Mark Word?
11.synchronized底层是怎么通过monitor进行加锁的?
12.synchronized的锁重入、锁消除、锁升级原理?无锁、偏向锁、轻量级锁、自旋、重量级锁
13.synchronized怎么保证可见性、有序性、原子性?
JAVA并发专题《结丹篇》
- JDK底层Unsafe类是个啥东西?
15.unsafe类的CAS是怎么保证原子性的?
16.Atomic原子类体系讲解
17.AtomicInteger、AtomicBoolean的底层原理
18.AtomicReference、AtomicStampReference底层原理
19.Atomic中的LongAdder底层原理之分段锁机制
20.Atmoic系列Strimped64分段锁底层实现源码剖析
JAVA并发专题《金丹篇》
21.AQS是个啥?为啥说它是JAVA并发工具基础框架?
22.基于AQS的互斥锁底层源码深度剖析
23.基于AQS的共享锁底层源码深度剖析
24.ReentrantLock是怎么基于AQS实现独占锁的?
25.ReentrantLock的Condition机制底层源码剖析
26.CountDownLatch 门栓底层源码和实现机制深度剖析
27.CyclicBarrier 栅栏底层源码和实现机制深度剖析
28.Semaphore 信号量底层源码和实现机深度剖析
29.ReentrantReadWriteLock 读写锁怎么表示?
- ReentrantReadWriteLock 读写锁底层源码和机制深度剖析
JAVA并发专题《元神篇》并发数据结构篇
31.CopyOnAarrayList 底层分析,怎么通过写时复制副本,提升并发性能?
32.ConcurrentLinkedQueue 底层分析,CAS 无锁化操作提升并发性能?
33.ConcurrentHashMap详解,底层怎么通过分段锁提升并发性能?
34.LinkedBlockedQueue 阻塞队列怎么通过ReentrantLock和Condition实现?
35.ArrayBlockedQueued 阻塞队列实现思路竟然和LinkedBlockedQueue一样?
36.DelayQueue 底层源码剖析,延时队列怎么实现?
37.SynchronousQueue底层原理解析
JAVA并发专题《飞升篇》线程池底层深度剖析
- 什么是线程池?看看JDK提供了哪些默认的线程池?底层竟然都是基于ThreadPoolExecutor的?
39.ThreadPoolExecutor 构造函数有哪些参数?这些参数分别表示什么意思?
40.内部有哪些变量,怎么表示线程池状态和线程数,看看道格.李大神是怎么设计的?
- ThreadPoolExecutor execute执行流程?怎么进行任务提交的?addWorker方法干了啥?什么是workder?
- ThreadPoolExecutor execute执行流程?何时将任务提交到阻塞队列? 阻塞队列满会发生什么?
- ThreadPoolExecutor 中的Worker是如何执行提交到线程池的任务的?多余Worker怎么在超出空闲时间后被干掉的?
- ThreadPoolExecutor shutdown、shutdownNow内部核心流程
- 再回头看看为啥不推荐Executors提供几种线程池?
- ThreadPoolExecutor线程池篇总结