1. yield()
应该做的是让当前运行线程回到可运行状态,以允许具有相同优先级的其他线程获得运行机会。因此,使用yield()的
目的是让相同优先级的线程之间能适当的轮转执行。
2.wait()
就是说线程在获取对象锁后,主动释放对象锁,同时本线程休眠。直到有其它线程调用对象的notify()
唤醒该线程,才能继续获取对象锁,并继续执行;
3.相应的notify()
就是对对象锁的唤醒操作。
synchronized关键字
首先我们先来了解一下互斥锁,互斥锁:就是能达到互斥访问目的的锁。
如果对一个变量加上互斥锁,那么在同一时刻,该变量只能有一个线程能访问,即当一个线程访问临界资源时,其他线程只能等待。
在Java中,每一个对象都有一个锁标记(monitor),也被称为监视器,当多个线程访问对象时,只有获取了对象的锁才能访问。
在我们编写代码的时候,可以使用synchronized
修饰对象的方法或者代码块,当某个线程访问这个对象synchronized
方法或者代码块时,就获取到了这个对象的锁,这个时候其他对象是不能访问的,只能等待获取到锁的这个线程执行完该方法或者代码块之后,才能执行该对象的方法。
1.在线程调用synchronized
的方法时,其他synchronized
的方法是不能被访问的,道理很简单,一个对象只有一把锁;
2.当一个线程在访问对象的synchronized
方法时,其他线程可以访问该对象的非synchronized
方法,因为访问非synchronized
不需要获取锁,是可以随意访问的;
3.如果一个线程A需要访问对象object1
的synchronized
方法fun1
,另外一个线程B需要访问对象object2
的synchronized
方法fun1
,即使object1
和object2
是同一类型),也不会产生线程安全问题,因为他们访问的是不同的对象,所以不存在互斥问题。
上述代码就是synchronized
代码块添加锁的两种方式,可以发现添加synchronized
代码块,要比直接在方法上添加synchronized
关键字更加灵活。
当我们用sychronized
关键字修饰方法时,这个方法只能同时让一个线程访问,但是有时候很可能只有一部分代码需要同步,而这个时候使用sychronized
关键字修饰的方法是做不到的,但是使用sychronized
代码块就可以实现这个功能。
并且如果一个线程执行一个对象的非static synchronized
方法,另外一个线程需要执行这个对象所属类的static synchronized
方法,此时不会发生互斥现象,因为访问static synchronized
方法占用的是类锁,而访问非static synchronized
方法占用的是对象锁,所以不存在互斥现象。