例子:创建三个窗口卖票,总票数为100张,使用实现Runnable接口的方式来实现
1.问题:卖票的过程中,出现了重票错票。原因:出现了线程安全问题。
2.出现线程安全的原因:当某个线程操作车票的过程中,尚未操作完成的时候,其他线程参与进来也操作车票。出现了,多个线程同时操作同一个资源的情况。
3.如何解决:当一个或多个线程在操作同一个资源的时候,应该控制在同一个时间只能有一个线程操作数据,其他线程不能参与进来,直到此线程操作完毕才能让其他线程操作这个资源。
4,在java中,通过同步的机制来解决线程的安全问题。
方式一:同步代码块
synchronized(同步监视器){
需要被同步的代码
}
说明:操作共享数据的代码,即为需要被同步的代码。
共享数据:多个线程共享的数据。
同步监视器:俗称:“锁”,任何一个对象都可以作为锁。但是多个线程操作同一个数据的时候,线程的锁,必须是相同的。
在实现Runnable实现多线程的时候可以考虑使用this关键字来作为同步代码块的锁。在继承Thread类的方式实现多线程的时候慎用this关键字作为锁。
方式二:同步方法:
[权限修饰符] synchronized [返回值类型] [方法名]{
同步代码
}
在实现Runnable接口来创建多线程的时候,同步方法所用的锁用的是默认的锁:this
在继承Thread类来创建所线程的时候,同步方法所用的锁默认用的是当前类的字节码文件。
同步的方式,解决了线程的安全问题,在同步的代码块或方法中,只存在一个线程。
方式三: Lock 锁。显式锁。jdk 5.0新增。
第一步,先实例化一个lock对象。
第二步,上锁。lock对象.lock();
第三步,解锁。lock对象.unlock();
lock方式需要手动的加锁解锁。而,synchronized关键字是自动的加锁解锁。