我们再回顾一下原子性:
原子性提供了互斥访问 ,同一时刻只有一个线程能对他进行操作 .
同一时刻只有一个线程能对其进行操作的 除了Atomic包之外还有锁
锁分为两种:
____________________________________________________________________________
依赖于JVM去实现锁,因此在这个关键字作用对象的作用范围内,都是同一时刻只能有一个线程对其进行操作的。
synchronized是java中的一个关键字,是一种同步锁。它可以修饰的对象主要有四种:
修饰代码块:大括号括起来的代码,作用于调用的对象
修饰方法:整个方法,作用于调用的对象
修饰静态方法:整个静态方法,作用于所有对象
修饰类:括号括起来的部分,作用于所有对象
____________________________________________________________________________
synchronized 修饰一个代码块
被修饰的代码称为同步语句块,作用的范围是大括号括起来的部分。作用的对象是调用这段代码的对象。
这里用到了 线程池 , 为什么要用线程池呢?
如果不使用线程池,这里一个类对象(example1) 两次调用同一个方法 , 本身就是同步执行的. 因此没法验证具体的影响.
而我们加上线程池之后相当于分别启动了两个线程去执行. (一个没等另一个完就执行了)
public class SynchronizedExample {
public void test(int j){
synchronized (this){
for (int i = 0; i < 10; i++) {
log.info("test - {} - {}",j,i);
}
}
}
//使用线程池方法进行测试:
public static void main(String[] args) {
SynchronizedExample example1 = new SynchronizedExample();
SynchronizedExample example2 = new SynchronizedExample();
ExecutorService executorService = Executors.newCachedThreadPool();
executorService.execute(()-> example1.test(1));
executorService.execute(()-> example2.test(2));
}
}
结果:不同对象之间的操作互不影响
tip: 当一个方法里都是同步的代码块时, 他的作用和直接修饰方法是一样的
____________________________________________________________________________
synchronized 修饰一个方法
被修饰的方法称为同步方法,作用的范围是大括号括起来的部分,作用的对象是调用这段代码的对象。
public class SynchronizedExample
public synchronized void test(int j){
for (int i = 0; i < 10; i++) {
log.info("test - {} - {}",j,i);
}
}
//验证方法与上面相同
...
}
tip2:如果当前类是一个父类,子类调用父类的被synchronized修饰的方法,不会携带synchronized属性,因为synchronized不属于方法声明的一部分
____________________________________________________________________________
synchronized 修饰一个静态方法
作用的范围是synchronized 大括号括起来的部分,作用的对象是这个类的所有对象。
验证:
public class SynchronizedExample{
public static synchronized void test(int j){
for (int i = 0; i < 10; i++) {
log.info("test - {} - {}",j,i);
}
}
//验证方法与上面相同
...
}
结果:同一时间只有一个线程可以执行
synchronized 修饰一个类
public class SynchronizedExample{
public static void test(int j){
synchronized (SynchronizedExample.class){
for (int i = 0; i < 10; i++) {
log.info("test - {}-{}",j,i);
}
}
}
//验证方法与上面相同
...
}
结果:同一时间只有一个线程可以执行
原子性操作各方法间的对比
synchronized:不可中断锁,适合竞争不激烈,可读性好
Lock:可中断锁,多样化同步,竞争激烈时能维持常态
Atomic:竞争激烈时能维持常态,比Lock性能好,每次只能同步一个值