4.3原子性-锁
实现锁可使用:
synchronized关键字:依赖JVM实现
Lock:依赖特殊的CPU指令,代码实现。 如:ReentrantLock
Synchronized
1.修饰对象及作用范围
修饰代码块:大括号括起来的代码,作用于调用的对象
修饰方法:整个方法,作用于调用的对象
修饰静态方法:整个静态方法,作用于所有对象
修饰类:括号括起来的部分,作用于所有对象
2.无Synchronized修饰的代码
实验代码
package com.moluo.concurrency.sync;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class NoSynchronizedExample {
public static void test(String tag) {
for (int i = 0; i < 10; i++) {
System.out.println("tag: " + tag + ", output:" + i);
}
}
public static void main(String[] args) {
// 案例一:1个对象,2个线程,在运行程序过程中,执行权可能被夺走
NoSynchronizedExample example = new NoSynchronizedExample();
ExecutorService executorService = Executors.newCachedThreadPool();
executorService.execute(() -> {
example.test("......");
});
executorService.execute(() -> {
example.test(">>>>>>");
});
executorService.shutdown();
}
}
输出结果
tag: ......, output:0
tag: ......, output:1
tag: ......, output:2
tag: ......, output:3
tag: ......, output:4
tag: ......, output:5
tag: ......, output:6
tag: ......, output:7
tag: >>>>>>, output:0 // 执行权被夺走
tag: ......, output:8
tag: >>>>>>, output:1
tag: >>>>>>, output:2
tag: >>>>>>, output:3
tag: ......, output:9
tag: >>>>>>, output:4
tag: >>>>>>, output:5
tag: >>>>>>, output:6
tag: >>>>>>, output:7
tag: >>>>>>, output:8
tag: >>>>>>, output:9
注意:由于代码的随机性,仅运行一次代码,你可能看不到执行权被夺走的情况,建议将循环次数10调到1000,却多次运行代码观察
结论
多个线程争抢cpu执行权,谁抢到算谁的。抢到执行权的线程
在运行程序过程中执行权可能被夺走
3.修饰代码块:大括号括起来的代码,作用于调用的对象
调用的对象
实验代码
package com.moluo.concurrency.sync;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class SynchronizedCodeBlockExample {
public void test(String tag) {
synchronized (this) {
for (int i = 0; i < 10; i++) {
System.out.println("tag: " + tag + ", output:" + i);
}
}
}
public static void main(String[] args) {
// 案例一:1个对象,2个线程,在运行程序过程中,执行权不可被夺走
// SynchronizedCodeBlockExample example = new SynchronizedCodeBlockExample();
// ExecutorService executorService = Executors.newCachedThreadPool();
// executorService.execute(() -> {
// example.test("......");
// });
// executorService.execute(() -> {
// example.test(">>>>>>");
// });
// executorService.shutdown();
// 案例二:2个对象,2个线程,在运行程序过程中,执行权可能被夺走
SynchronizedCodeBlockExample example1 = new SynchronizedCodeBlockExample();
SynchronizedCodeBlockExample example2 = new SynchronizedCodeBlockExample();
ExecutorService executorService = Executors.newCachedThreadPool();
executorService.execute(() -> {
example1.test("......");
});
executorService.execute(() -> {
example2.test(">>>>>>");
});
executorService.shutdown();
}
}
案例一输出结果
tag: ......, output:0
tag: ......, output:1
tag: ......, output:2
tag: ......, output:3
tag: ......, output:4
tag: ......, output:5
tag: ......, output:6
tag: ......, output:7
tag: ......, output:8
tag: ......, output:9
tag: >>>>>>, output:0
tag: >>>>>>, output:1
tag: >>>>>>, output:2
tag: >>>>>>, output:3
tag: >>>>>>, output:4
tag: >>>>>>, output:5
tag: >>>>>>, output:6
tag: >>>>>>, output:7
tag: >>>>>>, output:8
tag: >>>>>>, output:9
案例二输出结果
tag: ......, output:0
tag: ......, output:1
tag: ......, output:2
tag: ......, output:3
tag: ......, output:4
tag: ......, output:5
tag: ......, output:6
tag: ......, output:7
tag: ......, output:8
tag: >>>>>>, output:0
tag: >>>>>>, output:1
tag: >>>>>>, output:2
tag: >>>>>>, output:3
tag: >>>>>>, output:4
tag: >>>>>>, output:5
tag: >>>>>>, output:6
tag: >>>>>>, output:7
tag: >>>>>>, output:8
tag: ......, output:9 //执行权被夺走
tag: >>>>>>, output:9
注意:由于代码的随机性,仅运行一次代码,你可能看不到执行权被夺走的情况,建议将循环次数10调到1000,却多次运行代码观察
结论
被synchronized修饰的代码块作用域为调用的对象
。一个对象可以保证线程安全,两个对象无法保证线程安全
4.修饰方法:整个方法,作用于调用的对象
调用的对象
实验代码
package com.moluo.concurrency.sync;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* @author moluo
* @since 2020/6/27
*/
public class SynchronizedMethodExample {
public synchronized void test(String tag) {
for (int i = 0; i < 10; i++) {
System.out.println("tag: " + tag + ", output:" + i);
}
}
public static void main(String[] args) {
// 案例一:1个对象,2个线程,在运行程序过程中,执行权不可被夺走
SynchronizedMethodExample example = new SynchronizedMethodExample();
ExecutorService executorService = Executors.newCachedThreadPool();
executorService.execute(() -> {
example.test("......");
});
executorService.execute(() -> {
example.test(">>>>>>");
});
executorService.shutdown();
// two object,cross execute
// SynchronizedMethodExample example1 = new SynchronizedMethodExample();
// SynchronizedMethodExample example2 = new SynchronizedMethodExample();
// ExecutorService executorService = Executors.newCachedThreadPool();
// executorService.execute(() -> {
// example1.test("......");
// });
// executorService.execute(() -> {
// example2.test(">>>>>>");
// });
// executorService.shutdown();
}
}
案例一输出结果
tag: ......, output:0
tag: ......, output:1
tag: ......, output:2
tag: ......, output:3
tag: ......, output:4
tag: ......, output:5
tag: ......, output:6
tag: ......, output:7
tag: ......, output:8
tag: ......, output:9
tag: >>>>>>, output:0
tag: >>>>>>, output:1
tag: >>>>>>, output:2
tag: >>>>>>, output:3
tag: >>>>>>, output:4
tag: >>>>>>, output:5
tag: >>>>>>, output:6
tag: >>>>>>, output:7
tag: >>>>>>, output:8
tag: >>>>>>, output:9
案例二输出结果
tag: ......, output:0
tag: >>>>>>, output:0
tag: >>>>>>, output:1
tag: >>>>>>, output:2
tag: >>>>>>, output:3
tag: >>>>>>, output:4
tag: >>>>>>, output:5
tag: >>>>>>, output:6
tag: >>>>>>, output:7
tag: ......, output:1 // 执行权被夺走
tag: ......, output:2
tag: >>>>>>, output:8
tag: >>>>>>, output:9
tag: ......, output:3
tag: ......, output:4
tag: ......, output:5
tag: ......, output:6
tag: ......, output:7
tag: ......, output:8
tag: ......, output:9
结论
被synchronized修饰的方法作用域为调用的对象
。一个对象可以保证线程安全,两个对象无法保证线程安全
5.修饰静态方法:整个静态方法,作用于所有对象
所有对象
实验代码
package com.moluo.concurrency.sync;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class SynchronizedStaticMethodExample {
public static synchronized void test(String tag) {
for (int i = 0; i < 10; i++) {
System.out.println("tag: " + tag + ", output:" + i);
}
}
public static void main(String[] args) {
// 案例一:1个对象,2个线程,在运行程序过程中,执行权不可被夺走
// SynchronizedStaticMethodExample example = new SynchronizedStaticMethodExample();
// ExecutorService executorService = Executors.newCachedThreadPool();
// executorService.execute(() -> {
// example.test("......");
// });
// executorService.execute(() -> {
// example.test(">>>>>>");
// });
// executorService.shutdown();
// 案例二:2个对象,2个线程,在运行程序过程中,执行权不可被夺走
SynchronizedStaticMethodExample example1 = new SynchronizedStaticMethodExample();
SynchronizedStaticMethodExample example2 = new SynchronizedStaticMethodExample();
ExecutorService executorService = Executors.newCachedThreadPool();
executorService.execute(() -> {
example1.test("......");
});
executorService.execute(() -> {
example2.test(">>>>>>");
});
executorService.shutdown();
}
}
案例一输出结果
tag: ......, output:0
tag: ......, output:1
tag: ......, output:2
tag: ......, output:3
tag: ......, output:4
tag: ......, output:5
tag: ......, output:6
tag: ......, output:7
tag: ......, output:8
tag: ......, output:9
tag: >>>>>>, output:0
tag: >>>>>>, output:1
tag: >>>>>>, output:2
tag: >>>>>>, output:3
tag: >>>>>>, output:4
tag: >>>>>>, output:5
tag: >>>>>>, output:6
tag: >>>>>>, output:7
tag: >>>>>>, output:8
tag: >>>>>>, output:9
案例二输出结果
tag: ......, output:0
tag: ......, output:1
tag: ......, output:2
tag: ......, output:3
tag: ......, output:4
tag: ......, output:5
tag: ......, output:6
tag: ......, output:7
tag: ......, output:8
tag: ......, output:9
tag: >>>>>>, output:0
tag: >>>>>>, output:1
tag: >>>>>>, output:2
tag: >>>>>>, output:3
tag: >>>>>>, output:4
tag: >>>>>>, output:5
tag: >>>>>>, output:6
tag: >>>>>>, output:7
tag: >>>>>>, output:8
tag: >>>>>>, output:9
结论
被synchronized修饰的静态方法作用域为所有对象
。一个对象可以保证线程安全,多个对象也可保证线程安全
6.修饰类:括号括起来的部分,作用于所有对象
所有对象
实验代码
package com.moluo.concurrency.sync;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class SynchronizedClassExample {
public static void test(String tag) {
synchronized (SynchronizedClassExample.class) {
for (int i = 0; i < 10; i++) {
System.out.println("tag: " + tag + ", output:" + i);
}
}
}
public static void main(String[] args) {
// 案例一:1个对象,2个线程,在运行程序过程中,执行权不可被夺走
// SynchronizedClassExample example = new SynchronizedClassExample();
// ExecutorService executorService = Executors.newCachedThreadPool();
// executorService.execute(() -> {
// example.test("......");
// });
// executorService.execute(() -> {
// example.test(">>>>>>");
// });
// executorService.shutdown();
// 案例二:2个对象,2个线程,在运行程序过程中,执行权不可被夺走
SynchronizedClassExample example1 = new SynchronizedClassExample();
SynchronizedClassExample example2 = new SynchronizedClassExample();
ExecutorService executorService = Executors.newCachedThreadPool();
executorService.execute(() -> {
example1.test("......");
});
executorService.execute(() -> {
example2.test(">>>>>>");
});
executorService.shutdown();
}
}
案例一输出结果:
tag: ......, output:0
tag: ......, output:1
tag: ......, output:2
tag: ......, output:3
tag: ......, output:4
tag: ......, output:5
tag: ......, output:6
tag: ......, output:7
tag: ......, output:8
tag: ......, output:9
tag: >>>>>>, output:0
tag: >>>>>>, output:1
tag: >>>>>>, output:2
tag: >>>>>>, output:3
tag: >>>>>>, output:4
tag: >>>>>>, output:5
tag: >>>>>>, output:6
tag: >>>>>>, output:7
tag: >>>>>>, output:8
tag: >>>>>>, output:9
案例二输出结果:
tag: ......, output:0
tag: ......, output:1
tag: ......, output:2
tag: ......, output:3
tag: ......, output:4
tag: ......, output:5
tag: ......, output:6
tag: ......, output:7
tag: ......, output:8
tag: ......, output:9
tag: >>>>>>, output:0
tag: >>>>>>, output:1
tag: >>>>>>, output:2
tag: >>>>>>, output:3
tag: >>>>>>, output:4
tag: >>>>>>, output:5
tag: >>>>>>, output:6
tag: >>>>>>, output:7
tag: >>>>>>, output:8
tag: >>>>>>, output:9
结论
被synchronized修饰的类作用域为所有对象
。一个对象可以保证线程安全,多个对象也可保证线程安全
Last updated
Was this helpful?