1. synchronized关键字
synchronized
用于实现同步操作,防止出现脏读,常用于修饰方法和代码块。
2. synchronized同步
当synchronized
用于修饰方法时,线程锁的对象是其自身,等同于synchronized(this){}
代码块,也等同于synchronized(锁对象){}
。
public class ObjectLock {
public synchronized void methodA() {
System.out.println(Thread.currentThread().getName() + ": methodA begin");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
}
System.out.println(Thread.currentThread().getName() + ": methodA end");
}
public void methodB() {
synchronized (this) {
System.out.println(Thread.currentThread().getName() + ": methodB begin");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
}
System.out.println(Thread.currentThread().getName() + ": methodB end");
}
}
public static class ThreadA extends Thread {
ObjectLock lock;
ThreadA(ObjectLock lock) {
this.lock = lock;
setName("A");
}
@Override
public void run() {
lock.methodA();
}
}
public static class ThreadB extends Thread {
ObjectLock lock;
ThreadB(ObjectLock lock) {
this.lock = lock;
setName("B");
}
@Override
public void run() {
lock.methodB();
}
}
public static class ThreadC extends Thread {
ObjectLock lock;
ThreadC(ObjectLock lock) {
this.lock = lock;
setName("C");
}
@Override
public void run() {
synchronized (lock) {
System.out.println(Thread.currentThread().getName() + ": methodC begin");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
}
System.out.println(Thread.currentThread().getName() + ": methodC end");
}
}
}
}
分别调用这三个线程
public static void main(String[] args) {
ObjectLock lock = new ObjectLock();
ThreadA threadA = new ThreadA(lock);
threadA.start();
ThreadB threadB = new ThreadB(lock);
threadB.start();
ThreadC threadC = new ThreadC(lock);
threadC.start();
}
输出
对象锁有几个注意点
-
不同的对象拥有不同的锁,相互之间是不同步的。
-
同步不具有继承性,子类的覆盖方法需要添加
synchronized
关键字。 -
多线程死锁问题,线程
ThreadA
和ThreadB
分别拥有lock1
和lock2
,当ThreadA
在请求lock2
和ThreadB
在请求lock1
时都将形成死锁,导致程序无法继续进行。public class DeadLock { public static void main(String[] args) { DeadLock lock1 = new DeadLock(); DeadLock lock2 = new DeadLock(); ThreadA threadA = new ThreadA(lock1, lock2); threadA.start(); ThreadB threadB = new ThreadB(lock1, lock2); threadB.start(); } public static class ThreadA extends Thread { DeadLock lock1, lock2; public ThreadA(DeadLock lock1, DeadLock lock2) { this.lock1 = lock1; this.lock2 = lock2; setName("A"); } @Override public void run() { synchronized (lock1) { System.out.println(Thread.currentThread().getName() + ": methodA begin"); try { Thread.sleep(2000); } catch (InterruptedException e) { } synchronized (lock2) { System.out.println(Thread.currentThread().getName() + ": methodAA"); } System.out.println(Thread.currentThread().getName() + ": methodA end"); } } } public static class ThreadB extends Thread { DeadLock lock1, lock2; public ThreadB(DeadLock lock1, DeadLock lock2) { this.lock1 = lock1; this.lock2 = lock2; setName("B"); } @Override public void run() { synchronized (lock2) { System.out.println(Thread.currentThread().getName() + ": methodB begin"); try { Thread.sleep(2000); } catch (InterruptedException e) { } synchronized (lock1) { System.out.println(Thread.currentThread().getName() + ": methodBB"); } System.out.println(Thread.currentThread().getName() + ": methodB end"); } } } }
3. synchronized静态同步
对静态方法添加同步操作,等同于等同于synchronized(对象对应Class类){}
代码块。
public class StaticLock {
public static void main(String[] args) {
ThreadA threadA = new ThreadA();
threadA.start();
ThreadB threadB = new ThreadB();
threadB.start();
}
public synchronized static void methodA() {
System.out.println(Thread.currentThread().getName() + ": methodA begin");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
}
System.out.println(Thread.currentThread().getName() + ": methodA end");
}
public static class ThreadA extends Thread {
ThreadA() {
setName("A");
}
@Override
public void run() {
StaticLock.methodA();
}
}
public static class ThreadB extends Thread {
ThreadB() {
setName("B");
}
@Override
public void run() {
synchronized (StaticLock.class) {
System.out.println(Thread.currentThread().getName() + ": methodB begin");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
}
System.out.println(Thread.currentThread().getName() + ": methodB end");
}
}
}
}
输出
4. synchronized和volatile
synchronized
解决了多个线程之间访问资源的同步性。volatile
增加了变量在多个线程之间的可见性,但不具备同步性,也不支持原子性。
例如SyncLock
有一个变量condition
,分别在不同线程中修改它
public class SyncLock {
private boolean condition = true;
public void methodA() {
System.out.println(Thread.currentThread().getName() + ": methodA begin");
while(condition) {
}
System.out.println(Thread.currentThread().getName() + ": methodA end");
}
public void stopMethodA() {
condition = false;
}
public static class ThreadA extends Thread {
SyncLock lock;
ThreadA(SyncLock lock) {
this.lock = lock;
}
@Override
public void run() {
lock.methodA();
}
}
public static class ThreadB extends Thread {
SyncLock lock;
ThreadB(SyncLock lock) {
this.lock = lock;
}
@Override
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
lock.stopMethodA();
}
}
}
测试代码,
public static void main(String[] args) {
SyncLock lock = new SyncLock();
ThreadA threadA = new ThreadA(lock);
threadA.start();
ThreadB threadB = new ThreadB(lock);
threadB.start();
}
methodA()
会一直在运行(如果不是,改用-server
服务器模式运行),除非使用volatile
关键字改变condition
的可见性。
private volatile boolean condition = true;
synchronized
同样可以使不同线程进入同步方法或同步代码块后,具有可视性。
public void methodA() {
System.out.println(Thread.currentThread().getName() + ": methodA begin");
while(condition) {
synchronized (this) {
}
}
System.out.println(Thread.currentThread().getName() + ": methodA end");
}
相关文章
Java synchronized关键字
Java 关键字strictfp、volatile和transient