- 从jdk1.5开始,java官方提供了更加强大的线程同步机制----通过显示的定义同步锁对象来实现同步
- 同步锁:我们通过Lock接口的实现类的对象来作为同步锁
这里我们说使用Lock锁的方式来解决线程的安全问题,那么我们要知道Lock锁是什么?
- 这里的Lock其实是一个接口
- 这个接口的全称:java.util.concurrent.locks.Lock
- 我们实际使用的锁其实是这个接口的一个实现类(ReentranlLock)的一个对象(这个Lock接口的实现类ReentranlLock类的一个实例化对象)
- 实例化ReenTranlLock(这个类中实现了Lock接口)
- 这里我们也就是要创建ReentranTLock类的对象
- 这里我们要注意,如果是使用Lock锁的方式解决继承Thread类的方式创建的多线程的安全问题的话,我们就需要将这个创建的ReentranTLock对象的对应引用修饰为static
- 调用锁定方法
- 锁定方法:lock()方法
- 我们的锁定方法一般放在try中
- 调用解锁方法
- 解锁方法:unLock()方法
- 我们的解锁方法我们一般是放在finally中
这里我们举一个使用Lock锁解决实现Runnable接口的方式创建的多线程的安全问题的例子:
package 多线程;
import java.util.concurrent.locks.ReentrantLock;
class Window5 implements Runnable{
private int ticket=100;
ReentrantLock lock=new ReentrantLock(true);
public void run(){
while(true){
try{
lock.lock();//这里使我们调用的锁(ReentrantLock类的对象)的锁定方法
if (ticket > 0) {
System.out.println(Thread.currentThread().getName() + "正在卖票,票号为:" + ticket);
ticket--;
} else {
break;
}
}finally{
lock.unlock();//这里使我们调用这个实现类的开锁方法
}
}
}
}
public class Window5Test {
public static void main(String[] args) {
Window5 window5=new Window5();
Thread thread=new Thread(window5);
Thread thread1=new Thread(window5);
Thread thread2=new Thread(window5);
thread.setName("窗口一");
thread1.setName("窗口二");
thread2.setName("窗口三");
thread.start();
thread1.start();
thread2.start();
}
}
-
我们一般在使用Lock锁的方式解决线程安全问题时我们可以将我们的锁定方法的调用写在try中的第一句,然后将我们的解锁方法写在我们的finally中,这个时候我们就算是try中的需要同步的代码发生了异常,那么这个时候我们的锁也会在finally中关闭,就不会出现如果锁定之后发生异常之后不执行开锁方法而导致的后面执行的代码都变成了单线程的形式的情况
-
我们创建ReentrantLock对象的时候可以为这个构造方法中传递参数,这里可以传递一个boolean类型的值,如果我们调用空构造方法的话就会自动默认为这个参数为false,如果我们传递参数的话,那么我们传什么就是什么,如果我们传了false就是不公平(这个时候我们就是一个线程可能多次执行),如果我们传入的是true,那么这个时候我们就是公平的(也就是一个线程执行完就换一个线程,将所有线程执行一次之后再开始循环)


![Lock锁解决线程安全问题[java] Lock锁解决线程安全问题[java]](http://www.mshxw.com/aiimages/31/591536.png)
