1.标准访问
class Phone{
public synchronized void sendEmail() throws Exception {
System.out.println("**sendEmail");
}
public synchronized void sendSMS() throws Exception {
System.out.println("**sendSMS");
}
}
public class Lock8Demo {
public static void main(String[] args) throws InterruptedException {
Phone phone=new Phone();
new Thread(()->{
try{
phone.sendEmail();
}catch (Exception e){
e.printStackTrace();
}
},"A").start();
new Thread(()->{
try{
phone.sendSMS();
}catch (Exception e){
e.printStackTrace();
}
},"B").start();
}
}
两个方法均使用synchronized关键字修饰,A、B两线程互斥。线程的执行顺序,是根据cpu的分配情况,而不是根据代码的先后次序,因此打印结果是1,2或者2,1不确定。
2.线程休眠
对sendEmail()方法进行如下修改:
public synchronized void sendEmail() throws Exception {
TimeUnit.SECONDS.sleep(4);
System.out.println("**sendEmail");
}
一个对象只有一把锁,当一个线程获取了该对象的锁之后,其他线程无法获取该对象的锁,所以无法访问该对象的其他synchronized实例方法。(先到先得)
A、B线程执行的先后顺序依然是不确定的,因此打印结果是1,2或者2,1不确定。
3.新增普通方法
在Phone类中新增普通“sayHellow”方法:
public void sayHellow() throws Exception {
System.out.println("**sayHellow");
}
修改线程B中调用的方法
phone.sayHellow();
//phone.sendSMS();
因为普通方法与同步方法没有冲突,所以“sayHellow”先被打印(此时A线程被暂停)
4.两个对象调用两个线程
将线程C注释掉,再新建一个对象:
Phone phone1=new Phone();
修改线程B中调用sendSMS()方法及对象:
//phone.sayHellow();
//phone.sendSMS();
phone1.sendSMS();
每个对象都有一个对象锁,不同的对象,他们的锁不会互相影响。
所以两线程并行执行,“sendSMS”先被打印。
5.一个对象调用两个静态同步方法
在两个同步方法前加修饰词static:
public static synchronized void sendEmail() throws Exception
public static synchronized void sendSMS() throws Exception
修改线程B中调用sendSMS()方法的对象:
phone.sendSMS();
//phone1.sendSMS();
同1理,打印结果是1,2或者2,1不确定。
6.两个对象调用两个静态同步方法
修改线程B中调用sendSMS()方法的对象:
//phone.sendSMS();
phone1.sendSMS();
当synchronized作用于静态方法时,其锁就是当前类的class锁,不属于某个对象。
虽然对象不同,但属于同一个类,线程仍需要等待上一个对象结束线程,释放锁以后,才能进行。
由于A、B线程执行的先后顺序依然是不确定的,因此打印结果是1,2或者2,1不确定。
7.一个对象调用一个静态同步方法和一个普通同步方法
去掉sendSMS()同步方法中的修饰词static,并修改线程B中调用sendSMS()方法的对象:
phone.sendSMS();
//phone1.sendSMS();
8.两个对象调用一个静态同步方法和一个普通同步方法
修改线程B中调用sendSMS()方法的对象:
//phone.sendSMS();
phone1.sendSMS();
同7理,两线程并行执行,“sendSMS”先被打印。
补充:
synchronized实现同步的基础:Java中每一个对象都可以作为锁。
具体表现为以下3种形式:
①对于普通同步方法,锁是当前实例对象;
②对于同步方法块,锁是synchronized括号里配置的对象;
③对于静态同步方法,锁是当前类的class对象;