Atomic原子性提供了互斥访问。同一时刻只能由一个线程来操作。除了Atomic原子性,还有锁。
jdk提供的锁主要分2类
1、Synchronized:一种依赖JVM去实现锁的关键字,Synchronized,在这个对象作用的范围内,都是同一时刻,只能有一个线程去操作。注意是,作用对象的作用范围内。
2、另一种jdk代码层面的锁,jdk里面提供了一个Lock的接口,主要是依赖特殊的CPU指令,实现类中比较有代表性的是ReentrantLock。
Synchronized
一种同步锁,修改的对象主要有4种:
- 修饰代码块:大括号括起来的代码,也就是同步语句块,它的作用范围是大括号括起来的代码,作用对象是调用代码块的对象。
- 修饰方法:被称为同步方法,作用范围为整个方法,作用对象是也是调用该方法的对象。
- 修饰静态方法:作用范围整个静态方法,作用对象是这个类的所有对象。
- 修饰类:修饰内容是后面Synchronized括号括起来的部分,作用对象也是这个类的所有对象。
代码说明:
一、启用不同进程,同一对象调用,调用同一方法。
package com.yanxizhu.demo.concurrency.sync;
import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* @description: Synchronized修饰代码块、修改方法,作用对象为调用对象
* 这里测试,同一对象,启动不同进程,调同一方法
* @author: <a href="mailto:batis@foxmail.com">清风</a>
* @date: 2022/4/20 22:44
* @version: 1.0
*/
@Slf4j
public class DemoSynchronizedOne {
/**
* 修饰代码块,大括号被称为 同步代码块,
* 作用范围:代码块内
* 作用对象:调用代码块的对象
*/
public void test1() {
synchronized (this) {
for (int i = 0; i < 10 ;i ++){
log.info("test1 ...i={}",i);
}
}
}
/**
* 修饰方法,该方法被称为同步方
* 作为范围:整个test2方法
* 作用对象:调用代码块的对象
*/
public synchronized void test2() {
for (int i = 0; i < 10 ;i ++){
log.info("test2 ...i={}",i);
}
}
public static void main(String[] args) {
DemoSynchronizedOne demoSynchronized = new DemoSynchronizedOne();
//线程池
ExecutorService executorService = Executors.newCachedThreadPool();
/**
* 说明: 为什么执行2次
* 如果不用线程池,下面2次调用都是同一线程,不能验证。
* 使用线程池,相当于用了2各进程去执行test1,不用等一个进程执行完,在执行第二个线程,
* 这样才能看到同一个对象的不同进程的执行情况。
*/
//-----------------------------------测试同一对象的方法test1-------------------------------------------
// 测试1:
executorService.execute(() -> {
demoSynchronized.test1();
});
executorService.execute(() -> {
demoSynchronized.test1();
});
/* 输出结果:
23:33:52.670 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test1 ...i=0
23:33:52.674 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test1 ...i=1
23:33:52.674 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test1 ...i=2
23:33:52.674 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test1 ...i=3
23:33:52.674 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test1 ...i=4
23:33:52.674 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test1 ...i=5
23:33:52.674 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test1 ...i=6
23:33:52.674 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test1 ...i=7
23:33:52.674 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test1 ...i=8
23:33:52.674 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test1 ...i=9
23:33:52.674 [pool-1-thread-2] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test1 ...i=0
23:33:52.675 [pool-1-thread-2] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test1 ...i=1
23:33:52.675 [pool-1-thread-2] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test1 ...i=2
23:33:52.675 [pool-1-thread-2] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test1 ...i=3
23:33:52.675 [pool-1-thread-2] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test1 ...i=4
23:33:52.675 [pool-1-thread-2] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test1 ...i=5
23:33:52.675 [pool-1-thread-2] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test1 ...i=6
23:33:52.675 [pool-1-thread-2] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test1 ...i=7
23:33:52.675 [pool-1-thread-2] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test1 ...i=8
23:33:52.675 [pool-1-thread-2] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test1 ...i=9*/
//-----------------------------------测试同一对象的方法test2-------------------------------------------
// 测试2:
executorService.execute(() -> {
demoSynchronized.test2();
});
executorService.execute(() -> {
demoSynchronized.test2();
});
/* 输出结果:
23:33:24.291 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test2 ...i=0
23:33:24.295 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test2 ...i=1
23:33:24.296 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test2 ...i=2
23:33:24.296 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test2 ...i=3
23:33:24.296 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test2 ...i=4
23:33:24.296 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test2 ...i=5
23:33:24.296 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test2 ...i=6
23:33:24.296 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test2 ...i=7
23:33:24.296 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test2 ...i=8
23:33:24.296 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test2 ...i=9
23:33:24.296 [pool-1-thread-2] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test2 ...i=0
23:33:24.296 [pool-1-thread-2] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test2 ...i=1
23:33:24.296 [pool-1-thread-2] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test2 ...i=2
23:33:24.296 [pool-1-thread-2] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test2 ...i=3
23:33:24.296 [pool-1-thread-2] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test2 ...i=4
23:33:24.296 [pool-1-thread-2] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test2 ...i=5
23:33:24.296 [pool-1-thread-2] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test2 ...i=6
23:33:24.296 [pool-1-thread-2] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test2 ...i=7
23:33:24.296 [pool-1-thread-2] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test2 ...i=8
23:33:24.296 [pool-1-thread-2] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedOne - test2 ...i=9*/
executorService.shutdown();
}
}
二、启动不同进程,不同对象,调用同一方法
package com.yanxizhu.demo.concurrency.sync;
import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
*
* @description: Synchronized修饰代码块、修改方法,作用对象为调用对象
* 这里测试,不同对象,启动不同进程,调同一方法
* @author: <a href="mailto:batis@foxmail.com">清风</a>
* @date: 2022/4/20 22:44
* @version: 1.0
*/
@Slf4j
public class DemoSynchronizedTwo {
/**
* 修饰代码块,大括号被称为 同步代码块,
* 作用范围:代码块内
* 作用对象:调用代码块的对象
*/
public void test1(int j) {
synchronized (this) {
for (int i = 0; i < 10 ;i ++){
log.info("test1 ...i={},j={}",i,j);
}
}
}
/**
* 修饰方法,该方法被称为同步方
* 作为范围:整个test2方法
* 作用对象:调用代码块的对象
*/
public synchronized void test2(int j) {
for (int i = 0; i < 10 ;i ++){
log.info("test2 ...i={},j={}",i,j);
}
}
public static void main(String[] args) {
DemoSynchronizedTwo demoSynchronizedTwo = new DemoSynchronizedTwo();
DemoSynchronizedTwo demoSynchronizedTwo2 = new DemoSynchronizedTwo();
//线程池
ExecutorService executorService = Executors.newCachedThreadPool();
//-----------------------------------测试同一对象的方法test1,作用代码块-------------------------------------------
// executorService.execute(()->{
// demoSynchronizedTwo.test1(1);
// demoSynchronizedTwo2.test1(2);
// });
/* 输出结果:
23:28:57.763 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test1 ...i=0,j=1
23:28:57.768 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test1 ...i=1,j=1
23:28:57.768 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test1 ...i=2,j=1
23:28:57.768 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test1 ...i=3,j=1
23:28:57.768 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test1 ...i=4,j=1
23:28:57.768 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test1 ...i=5,j=1
23:28:57.768 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test1 ...i=6,j=1
23:28:57.769 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test1 ...i=7,j=1
23:28:57.769 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test1 ...i=8,j=1
23:28:57.769 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test1 ...i=9,j=1
23:28:57.769 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test1 ...i=0,j=2
23:28:57.769 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test1 ...i=1,j=2
23:28:57.769 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test1 ...i=2,j=2
23:28:57.769 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test1 ...i=3,j=2
23:28:57.769 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test1 ...i=4,j=2
23:28:57.769 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test1 ...i=5,j=2
23:28:57.769 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test1 ...i=6,j=2
23:28:57.769 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test1 ...i=7,j=2
23:28:57.769 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test1 ...i=8,j=2
23:28:57.769 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test1 ...i=9,j=2*/
/*
* 结论:说明作用于同步代码,不同对象的调用是相互不影响的
* */
//-----------------------------------测试同一对象的方法test2,作用方法-------------------------------------------
executorService.execute(()->{
demoSynchronizedTwo.test2(1);
demoSynchronizedTwo2.test2(2);
});
/* 输出结果:
23:34:56.130 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test2 ...i=0,j=1
23:34:56.135 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test2 ...i=1,j=1
23:34:56.135 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test2 ...i=2,j=1
23:34:56.135 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test2 ...i=3,j=1
23:34:56.135 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test2 ...i=4,j=1
23:34:56.135 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test2 ...i=5,j=1
23:34:56.135 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test2 ...i=6,j=1
23:34:56.135 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test2 ...i=7,j=1
23:34:56.135 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test2 ...i=8,j=1
23:34:56.135 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test2 ...i=9,j=1
23:34:56.135 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test2 ...i=0,j=2
23:34:56.135 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test2 ...i=1,j=2
23:34:56.135 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test2 ...i=2,j=2
23:34:56.135 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test2 ...i=3,j=2
23:34:56.135 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test2 ...i=4,j=2
23:34:56.135 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test2 ...i=5,j=2
23:34:56.135 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test2 ...i=6,j=2
23:34:56.135 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test2 ...i=7,j=2
23:34:56.135 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test2 ...i=8,j=2
23:34:56.135 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedTwo - test2 ...i=9,j=2*/
/*
* 结论:说明作用于方法,不同对象的调用是相互不影响的
* */
executorService.shutdown();
}
}
1和2对别结论:修饰带块和修改方法对别结论
1、当一个方法内都是用同步代码块修饰的,和修饰方法是一样的。
例如上面的:
public void test1(int j) {
synchronized (this) {
for (int i = 0; i < 10 ;i ++){
log.info("test1 ...i={},j={}",i,j);
}
}
}
等同与下面的修饰方法:
public synchronized void test2(int j) {
for (int i = 0; i < 10 ;i ++){
log.info("test2 ...i={},j={}",i,j);
}
}
2、修饰静态代码块和修饰方法,作用对象都是调用对象。
3、如果某个子类继承了上面的类,子类种test2方法是不带synchronized关键字的,因为synchronized不输入方法申明的一部分,如果子类想使用,则需要显示自己加synchronized。
三、不同对象调用同一方法,synchronized修改类和方法:
package com.yanxizhu.demo.concurrency.sync;
import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
*
* @description: Synchronized修饰静态方法、类
* @author: <a href="mailto:batis@foxmail.com">清风</a>
* @date: 2022/4/20 22:44
* @version: 1.0
*/
@Slf4j
public class DemoSynchronizedThredd {
//修饰类
public static void test1(int j) {
synchronized (DemoSynchronizedThredd.class) {
for (int i = 0; i < 10 ;i ++){
log.info("test1 ...i={},j={}",i,j);
}
}
}
//修饰静态方法
public static synchronized void test2(int j) {
for (int i = 0; i < 10 ;i ++){
log.info("test2 ...i={},j={}",i,j);
}
}
public static void main(String[] args) {
DemoSynchronizedThredd demoSynchronizedTwo = new DemoSynchronizedThredd();
DemoSynchronizedThredd demoSynchronizedTwo2 = new DemoSynchronizedThredd();
//线程池
ExecutorService executorService = Executors.newCachedThreadPool();
//-----------------------------------测试同一对象的方法test1,作用代码块-------------------------------------------
executorService.execute(()->{
demoSynchronizedTwo.test1(1);
demoSynchronizedTwo2.test1(2);
});
/* 输出结果:
23:49:32.176 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test1 ...i=0,j=1
23:49:32.181 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test1 ...i=1,j=1
23:49:32.181 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test1 ...i=2,j=1
23:49:32.181 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test1 ...i=3,j=1
23:49:32.181 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test1 ...i=4,j=1
23:49:32.181 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test1 ...i=5,j=1
23:49:32.181 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test1 ...i=6,j=1
23:49:32.181 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test1 ...i=7,j=1
23:49:32.181 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test1 ...i=8,j=1
23:49:32.181 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test1 ...i=9,j=1
23:49:32.181 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test1 ...i=0,j=2
23:49:32.181 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test1 ...i=1,j=2
23:49:32.181 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test1 ...i=2,j=2
23:49:32.181 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test1 ...i=3,j=2
23:49:32.181 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test1 ...i=4,j=2
23:49:32.181 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test1 ...i=5,j=2
23:49:32.181 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test1 ...i=6,j=2
23:49:32.181 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test1 ...i=7,j=2
23:49:32.181 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test1 ...i=8,j=2
23:49:32.181 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test1 ...i=9,j=2*/
//-----------------------------------测试同一对象的方法test2,作用方法-------------------------------------------
/* executorService.execute(()->{
demoSynchronizedTwo.test2(1);
demoSynchronizedTwo2.test2(2);
});*/
/* 输出结果:
23:47:13.674 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test2 ...i=0,j=1
23:47:13.681 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test2 ...i=1,j=1
23:47:13.681 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test2 ...i=2,j=1
23:47:13.681 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test2 ...i=3,j=1
23:47:13.681 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test2 ...i=4,j=1
23:47:13.681 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test2 ...i=5,j=1
23:47:13.681 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test2 ...i=6,j=1
23:47:13.681 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test2 ...i=7,j=1
23:47:13.681 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test2 ...i=8,j=1
23:47:13.681 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test2 ...i=9,j=1
23:47:13.681 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test2 ...i=0,j=2
23:47:13.681 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test2 ...i=1,j=2
23:47:13.681 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test2 ...i=2,j=2
23:47:13.681 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test2 ...i=3,j=2
23:47:13.681 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test2 ...i=4,j=2
23:47:13.681 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test2 ...i=5,j=2
23:47:13.681 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test2 ...i=6,j=2
23:47:13.681 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test2 ...i=7,j=2
23:47:13.681 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test2 ...i=8,j=2
23:47:13.681 [pool-1-thread-1] INFO com.yanxizhu.demo.concurrency.sync.DemoSynchronizedThredd - test2 ...i=9,j=2*/
executorService.shutdown();
/**
* 说明:修饰类和修改静态方法是一样的
*/
}
}
结论:修改类和静态方法,作用效果是一样的。
测试:
之前计数通过Atomic原子保证互斥性,现在通过Synchronized保证互斥性。
package com.yanxizhu.demo.concurrency.sync;
import com.yanxizhu.demo.concurrency.annotation.ThreadSafety;
import com.yanxizhu.demo.concurrency.annotation.UnThreadSafety;
import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
/**
* @description: 线程不安全,不正确的
* @author: <a href="mailto:batis@foxmail.com">清风</a>
* @date: 2022/4/19 19:28
* @version: 1.0
*/
@ThreadSafety
@Slf4j
public class DemoSemaphoreAndCountDownLatch {
//用户数量
private static final int clientsTotal = 5000;
//并发数量
private static final int concurrencyTotal = 200;
//累加总和
private static int count = 0;
public static void main(String[] args) throws InterruptedException {
ExecutorService executorService = Executors.newCachedThreadPool();
//信号量
final Semaphore semaphore = new Semaphore(concurrencyTotal);
//闭锁
final CountDownLatch countDownLatch = new CountDownLatch(clientsTotal);
for (int i = 0; i < clientsTotal; i++) {
executorService.execute(()->{
try {
semaphore.acquire();
add();
semaphore.release();
} catch (InterruptedException e) {
log.error("出现错误:【{}】", e.getMessage());
}
countDownLatch.countDown();
});
}
countDownLatch.await();
executorService.shutdown();
log.info("累加结果为count=【{}】",count);
}
/**
* 累加
*/
private synchronized static void add(){
count++;
}
}
原子性对比
synchronized:不可中断锁,适合竞争不激烈,可读性好
Lock:可中断锁,多样化同步,竞争激烈时能维持常态
Atomic:竞争激烈时能维持常态,比Lock性能好;只能同步一个值
评论 (0)