多线程存在的问题
案例
开启10个线程,每个线程中循环100次对result变量进行++自增,主线程等待10s后输出result值结果
public class SynchronizedCase {
private static Integer result = 0;
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
new Thread(() -> {
for (int j = 0; j < 100; j++) {
result++;
}
}).start();
}
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
System.out.println("执行结果 result : " + result);
}
}
结果
执行结果 result : 869
执行结果不一定是869,可能是其他的数,总之就是比正确的结果1000小
原因
result++这个操作的执行过程其实是3个步骤
- 读取result变量
- 将result变量进行+1
- 将result值再赋给result变量
详细的过程需要进行反编译来分析详细的过程,不是本文的重点,我们只需要知道这个三个过程就行
Synchronized
特性
- 互斥性:保证同一时刻只能有允许一个线程持有锁(对象或者静态类范围),通过这种多线程协调机制,保证其他线程必须等待该持有锁的线程执行完自己的任务释放了锁后,再获得锁的线程才能执行
- 可见性:保证了获得锁的线程执行后,对于共享变量所做的操作,对于其他获得锁的线程是可见的(即在获得锁时应获得最新共享变量的值)。
作用范围
- synchronized代码块加到对象上,则锁的范围为此对象
public class SynchronizedCase2 {
private static Integer result = 0;
public static void main(String[] args) {
//要加锁的对象
Object object = new Object();
for (int i = 0; i < 10; i++) {
new Thread(() -> {
synchronized (object) {
for (int j = 0; j < 100; j++) {
result++;
}
}
}).start();
}
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
System.out.println("执行结果 result : " + result);
}
}
- synchronized加在方法上,则锁的范围对调用方法的this对象
public class SynchronizedCase3 {
private static Integer result = 0;
public void increment(){
for (int j = 0; j < 100; j++) {
result++;
}
}
public static void main(String[] args) {
SynchronizedCase3 synchronizedCase3 = new SynchronizedCase3();
for (int i = 0; i < 10; i++) {
new Thread(() -> {
synchronizedCase3.increment();
}).start();
}
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
System.out.println("执行结果 result : " + result);
}
}
- synchronized代码块加到class上,则锁的范围为此类
public class SynchronizedCase4 {
private static Integer result = 0;
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
new Thread(() -> {
synchronized (SynchronizedCase4.class) {
for (int j = 0; j < 100; j++) {
result++;
}
}
}).start();
}
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
System.out.println("执行结果 result : " + result);
}
}
- synchronized添加在静态方法上,则锁的范围为此静态方法的类
public class SynchronizedCase5 {
private static Integer result = 0;
public static synchronized void increment(){
for (int j = 0; j < 100; j++) {
result++;
}
}
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
new Thread(() -> {
SynchronizedCase5.increment();
}).start();
}
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
System.out.println("执行结果 result : " + result);
}
}
注意点
- 一个线程加了synchronized对象锁,另一个线程没有加锁,是否能保证互斥性
public class SynchronizedCase5 {
private static Integer result = 0;
public static void main(String[] args) {
Object object = new Object();
new Thread(() -> {
synchronized (object) {
for (int j = 0; j < 50000; j++) {
result++;
}
}
}).start();
new Thread(() -> {
for (int j = 0; j < 50000; j++) {
result++;
}
}).start();
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
System.out.println("执行结果 result : " + result);
}
}
结果
执行结果 result : 60859
实际结果证明这种情况不能保证线程安全性
- 一个线程加了synchronized对象锁,另一个线程加synchronized到此class上,是否能保证互斥性
public class SynchronizedCase6 {
private static Integer result = 0;
public static void main(String[] args) {
SynchronizedCase6 synchronizedCase6 = new SynchronizedCase6();
synchronizedCase6.test();
}
public void test(){
new Thread(() -> {
synchronized (this) {
for (int j = 0; j < 50000; j++) {
result++;
}
}
}).start();
new Thread(() -> {
synchronized (SynchronizedCase6.class) {
for (int j = 0; j < 50000; j++) {
result++;
}
}
}).start();
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
System.out.println("执行结果 result : " + result);
}
}
结果文章来源:https://www.toymoban.com/news/detail-422878.html
执行结果 result : 59847
由于一个线程的锁是在this对象,另一个对象是在class上,不是同一个锁,所以保证不了互斥性文章来源地址https://www.toymoban.com/news/detail-422878.html
到了这里,关于synchronized各种使用场景的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!