java同步块也就是让同步块的代码只能同时有一个线程在执行,并且可以保证原子性和可见性。通过synchronized或者lock实现。
对象方法同步
package com.concurenny.chapter.seven;
/**
* 创建者:Mr lebron 创建时间:2017年11月17日 下午3:05:20
*/
public class ObjectMethodSynchronized {
public static void main(String[] args) {
final ObjectMethodSynchronized obj1 = new ObjectMethodSynchronized();
final ObjectMethodSynchronized obj2 = new ObjectMethodSynchronized();
Thread A = new Thread(()->{
obj1.add(1);
});
Thread B = new Thread(()->{
obj1.add(1);
});
Thread C = new Thread(()->{
obj2.add(1);
});
Thread D = new Thread(()->{
obj2.add(1);
});
A.start();
B.start();
C.start();
D.start();
}
private int count = 0;
/**
* 该对象的这个方法只能由一个线程同时执行。多个对象可以有多个线程执行。 因为synchronized持有的是当前对象的锁。
* 例如:ObjectMethodSynchronized obj1,ObjectMethodSynchronized obj2;线程A,B,C,D.
* A执行obj1.add(1),B执行obj1.add(1),C执行obj2.add(1),D执行obj2.add(1)
* 可能的情况:A获得obj1的锁,执行add,B发现锁obj1已经被拿了,阻塞进入等待队列。
* C获得obj2的锁,执行add,D发现锁obj2已经被拿了,阻塞进入等待队列。
* 此时就有两个线程在执行
*/
public synchronized int add(int plus) {
System.out.println(count += plus);
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return count;
}
}
静态方法同步
package com.concurenny.chapter.seven;
/**
* 创建者:Mr lebron 创建时间:2017年11月17日 下午3:05:20
*/
public class StaticMethodSynchronized {
public static void main(String[] args) {
final StaticMethodSynchronized obj1 = new StaticMethodSynchronized();
final StaticMethodSynchronized obj2 = new StaticMethodSynchronized();
Thread A = new Thread(()->{
obj1.add(1);
});
Thread B = new Thread(()->{
obj1.add(1);
});
Thread C = new Thread(()->{
obj2.add(1);
});
Thread D = new Thread(()->{
obj2.add(1);
});
A.start();
B.start();
C.start();
D.start();
}
private static int count = 0;
/**
* 这个方法只能由一个线程同时执行。 因为synchronized持有的是StaticMethodSynchronized这个类对象的锁,这个类对象只可能有一个
* 例如:ObjectMethodSynchronized obj1,ObjectMethodSynchronized obj2;线程A,B,C,D.
* A执行obj1.add(1),B执行obj1.add(1),C执行obj2.add(1),D执行obj2.add(1)
* 可能的情况:A获得类对象(ObjectMethodSynchronized)的锁,执行add,B发现锁类对象(ObjectMethodSynchronized)已经被拿了,阻塞进入等待队列。
* D发现锁类对象(ObjectMethodSynchronized)已经被拿了,阻塞进入等待队列,D发现锁类对象(ObjectMethodSynchronized)已经被拿了,阻塞进入等待队列。
* 此时只可能有一个线程在执行
*/
public synchronized static int add(int plus) {
System.out.println(count += plus);
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return count;
}
}对象方法同步块
package com.concurenny.chapter.seven;
/**
* 创建者:Mr lebron 创建时间:2017年11月17日 下午3:05:20
*/
public class ObjectMethodSynchronizedBlock {
public static void main(String[] args) {
final ObjectMethodSynchronizedBlock obj1 = new ObjectMethodSynchronizedBlock();
final ObjectMethodSynchronizedBlock obj2 = new ObjectMethodSynchronizedBlock();
Thread A = new Thread(()->{
obj1.add(1);
});
Thread B = new Thread(()->{
obj1.add(1);
});
Thread C = new Thread(()->{
obj2.add(1);
});
Thread D = new Thread(()->{
obj2.add(1);
});
A.start();
B.start();
C.start();
D.start();
}
private int count = 0;
/**
* 该对象的这个方法只能由一个线程同时执行。多个对象可以有多个线程执行。 因为synchronized持有的是当前对象的锁。
* 例如:ObjectMethodSynchronized obj1,ObjectMethodSynchronized obj2;线程A,B,C,D.
* A执行obj1.add(1),B执行obj1.add(1),C执行obj2.add(1),D执行obj2.add(1)
* 可能的情况:A获得obj1的锁,执行add,B发现锁obj1已经被拿了,阻塞进入等待队列。
* C获得obj2的锁,执行add,D发现锁obj2已经被拿了,阻塞进入等待队列。
* 此时就有两个线程在执行
*/
public int add(int plus) {
//这种方式的锁和方法同步的锁一样,都是该方法所属对象,只是可能在同步块的上方后者下面会有其他代码
System.out.println("进入同步块前:");
synchronized (this) {
System.out.println(count += plus);
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("退出同步块后:");
return count;
}
}
静态方法同步块
package com.concurenny.chapter.seven;
/**
* 创建者:Mr lebron 创建时间:2017年11月17日 下午3:05:20
*/
public class StaticMethodSynchronizedBlock {
public static void main(String[] args) {
final StaticMethodSynchronizedBlock obj1 = new StaticMethodSynchronizedBlock();
final StaticMethodSynchronizedBlock obj2 = new StaticMethodSynchronizedBlock();
Thread A = new Thread(()->{
obj1.add(1);
});
Thread B = new Thread(()->{
obj1.add(1);
});
Thread C = new Thread(()->{
obj2.add(1);
});
Thread D = new Thread(()->{
obj2.add(1);
});
A.start();
B.start();
C.start();
D.start();
}
private static int count = 0;
/**
*原理同对象方法同步块
*/
public static int add(int plus) {
//这种方式的锁和方法同步的锁一样,都是该StaticMethodSynchronizedBlock类对象
System.out.println("进入同步块前:");
synchronized (StaticMethodSynchronizedBlock.class) {
System.out.println(count += plus);
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("退出同步块后:");
return count;
}
}
本文深入探讨了Java中同步机制的应用,包括对象方法同步、静态方法同步及对应的同步块实现方式。通过实例展示了如何使用synchronized关键字及Lock接口来确保代码的原子性和可见性,防止多线程环境下出现的数据不一致问题。

被折叠的 条评论
为什么被折叠?



