互斥锁是JDK6中引入的新特性
使用规则
一、锁对象设置
a、修饰代码块时,需要设置一个引用类型对象作为锁的同步监视器对象
b、修饰实例方法时,默认的同步监视器对象是当前对象
c、修饰类方法(静态方法)时、默认的同步监视器对象是当前类的Class对象
二、根据锁对象的不同,一把锁同时最多只能被一个线程拥有
a、若锁对象已被当前线程持有,则其他线程需要等待持有锁的线程释放锁后才能继续执行,否则就阻塞
b、synchronized 添加在方法上时只针对该方法在多线程同步执行时只有一个在运行,其他线程使用对象内的其他没有添加synchronized 的方法可以正常使用
示例
当 synchronized 锁住多段不同的代码片段时,如果这些代码块使用的锁对象是同一个时
那么这些代码片段之间就是互斥的,多个线程不能同时执行他们
当 synchronized 添加在方法上时就以当前对象作为锁对象,如果是静态方法则以当前类的Class对象做为锁对象
public static synchronized void a() {
System.out.println("a执行中");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static synchronized void b() {
System.out.println("b执行中");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static synchronized void main(String[] args) {
Thread a = new Thread(() -> {
for(int i=0;i<10;i++) {
a();
}
});
Thread b = new Thread(() -> {
for(int i=0;i<10;i++) {
b();
}
});
a.start();
b.start();
}
另一种例子,最终结果输出 1,2,3,4,5......,结果没有被线程打乱
private static int a = 0;
public static Thread a(Integer lock) {
return new Thread(() -> {
synchronized (lock) {
a = a+1;
System.out.println(a);
}
});
}
public static void main(String[] args) {
for(int i=0;i<100;i++) {
Thread thread = a(0);
thread.start();
}
}