线程安全性之原子性——synchronized关键字
synchronized是java的一个关键字,是依赖JVM来实现锁。在这个关键字的作用对象的作用范围内,都只能有一个线程来执行
我们来看一下synchronized关键字的作用范围。他有四种作用范围
下面我将给出4中范围的代码模拟过程
先看前两种,修饰代码块和方法
@Slf4j
public class SynchronizedExample1 {
private static Logger log=LoggerFactory.getLogger(SynchronizedExample1.class);
/**
* 用synchronized修饰一个代码块,则作用的是它括号里的代码,作用的对象是调用这部分代码的对象
* 被修饰的代码被称作是同步语句块,
* 结果是两个进程可以交替执行
*/
private void test1(int j){
synchronized (this){
for(int i=0;i<10;i++){
log.info("test1-{} {}",j,i);
}
}
}
/**
* 用synchronized修饰一个方法,把关键字放到方法名中
* 作用的对象是调用这部分代码的对象
* 结果是两个进程可以交替执行
*/
public synchronized void test2(int j){
for(int i=0;i<10;i++){
log.info("test2-{} {}",j,i);
}
}
public static void main(String[] args) {
SynchronizedExample1 example1=new SynchronizedExample1();
SynchronizedExample1 example2=new SynchronizedExample1();
ExecutorService executorService= Executors.newCachedThreadPool();
executorService.execute(()->{
example1.test2(1);
});
executorService.execute(()->{
example2.test2(2);
});
}
}
yunxins我们先来测试一下修饰一个方法,即test2,运行结果来看一下
我们发现两个类的对象可以交替执行test2的方法。
我们来测试一下修饰一个代码块,即执行test1方法
结果发现,和上面运行结果基本一致,都是交替执行方法。
下面我们来看一下测试一个类和测试一个静态方法。
@Slf4j
public class SynchronizedExample2 {
private static Logger log=LoggerFactory.getLogger(SynchronizedExample2.class);
/**
* 用synchronized修饰一个类
* 此时,同一个时间,只有一个线程可以被执行
*/
private static void test1(int j){
synchronized (SynchronizedExample2.class){
for(int i=0;i<10;i++){
log.info("test1-{} {}",j,i);
}
}
}
/**
* 用synchronized修饰一个静态方法,把关键字放到方法名中
* 作用的对象是调用这部分代码的对象
* 此时,同一个时间,只有一个线程可以被执行
*/
public static synchronized void test2(int j){
for(int i=0;i<10;i++){
log.info("test2-{} {}",j,i);
}
}
public static void main(String[] args) {
SynchronizedExample2 example1=new SynchronizedExample2();
SynchronizedExample2 example2=new SynchronizedExample2();
ExecutorService executorService= Executors.newCachedThreadPool();
executorService.execute(()->{
example1.test1(1);
});
executorService.execute(()->{
example2.test1(2);
});
}
}
先测试一下test1方法,打印结果
此时发现,两个实例化的对象并不是交替执行,而是只让一个对象执行完之后另一个对象才执行。
用synchronized修饰一个静态方法时和它一样,也是先执行完一个对象的操作,在执行另一个对象 的操作。