1、普通的synchronized同步方法、和同步代码块,锁的是调用的对象
如下代码虽然用了两个线程分别调用buy1()、buy2()两个方法,但是,用的是同一个对象ticket1 调用的。执行时buy2()的调用要等到buy1()调用结束。
输出结果时等待3秒,先输出A===buy1,后输出B===buy2
public class LockTest {
public static void main(String[] args) throws InterruptedException {
Ticket4 ticket1 = new Ticket4();
new Thread(()->ticket1.buy1(),"A").start();
new Thread(()->ticket1.buy2(),"B").start();
}
}
class Ticket4{
public synchronized void buy1(){
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"===buy1");
}
public void buy2(){
synchronized(this) {
System.out.println(Thread.currentThread().getName() + "===buy2");
}
}
}
2、静态同步方法和普通同步方法:静态同步方法锁的是类的class模板,普通同步方法锁的是调用对象
虽然和上面一样都是同一个对象ticket1调用的,但是静态同步方法锁的是Ticket4的类模板,而普通同步方法锁的是new出来的ticket1对象。锁的不是同一个对象,所以buy3()方法的调用不用等buy1()结束,
输出结果时先输出B===buy3,线程A休眠3秒后输出A===buy1
public class LockTest {
public static void main(String[] args) throws InterruptedException {
Ticket4 ticket1 = new Ticket4();
new Thread(()->ticket1.buy1(),"A").start();
new Thread(()->ticket1.buy3(),"B").start();
}
}
class Ticket4{
public synchronized void buy1(){
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"===buy1");
}
public static synchronized void buy3(){
System.out.println(Thread.currentThread().getName() + "===buy3");
}
}
3、普通方法和普通同步方法:普通同步方法锁的是调用对象,普通方法没有锁
输出结果时先输出B===buy4,线程A休眠3秒后输出A===buy1
public class LockTest {
public static void main(String[] args) throws InterruptedException {
Ticket4 ticket1 = new Ticket4();
new Thread(()->ticket1.buy1(),"A").start();
new Thread(()->ticket1.buy4(),"B").start();
}
}
class Ticket4{
public synchronized void buy1(){
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"===buy1");
}
public void buy4(){
System.out.println(Thread.currentThread().getName() + "===buy4");
}
}