问题的提出
1、多个线程执行的不确定性引起执行结果的不稳定。
2、多个线程对账本的共享,会造成操作的不完整性,会破坏数据。
例 题
模拟火车站售票程序,开启三个窗口售票。
class Ticket implements Runnable {private int tick = 100;public void run(){while (true) {if (tick > 0) {System.out.println(Thread.currentThread().getName() + "售出车票,tick号为:" + tick--);} elsebreak;}}}class TicketDemo {public static void main(String[] args) {Ticket t = new Ticket();Thread t1 = new Thread(t);Thread t2 = new Thread(t);Thread t3 = new Thread(t);t1.setName("t1窗口");t2.setName("t2窗口");t3.setName("t3窗口");t1.start();t2.start();t3.start();}}
private int tick = 100;public void run() {while (true) {if (tick > 0) {try {Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName() + "售出车票,tick号为:" + tick--);}}}
1) 多线程出现了安全问题
2)问题的原因:
当多条语句在操作同一个线程共享数据时,一个线程对多条语句只执行了一部分,还没有执行完,另一个线程参与进来执行。导致共享数据的错误。
3)解决办法
对多条操作共享数据的语句,只能让一个线程都执行完,在执行过程中,其他线程不可以参与执行。
Synchronized的使用方法
lJava对于多线程的安全问题提供了专业的解决方式:同步代码块
1)synchronized (对象){
// 需要被同步的代码;
}
2)synchronized还可以放在方法声明中,表示整个方法
为同步方法。
例如:
public synchronized void show (String name){
….
}
同步锁(Lock)
从Java 5开始,Java提供了更强大的线程同步机制——通过显式定义同步锁对象来实现同步。同步锁使用Lock对象充当。
Lock是控制多个线程对共享资源进行访问的工具。锁提供了对共享资源的独占访问,每次只能有一个线程对Lock对象加锁,线程开始访问共享资源之前应先获得Lock对象。
在实现线程安全的控制中,比较常用的是ReentrantLock(可重入锁),可以显式加锁、释放锁。
class A {private final ReentrantLock lock = new ReenTrantLock();public void m() {lock.lock();try {// 保证线程安全的代码;} finally {lock.unlock();}}}
互斥锁
l 在Java语言中,引入了对象互斥锁的概念,来保证共享数据操作的完整性。
1、每个对象都对应于一个可称为互斥锁的标记,这个标记用来保证在任一时刻,只能有一个线程访问该对象。
2、关键字synchronized 来与对象的互斥锁联系。当某个对象用synchronized修饰时,表明该对象在任一时刻只能由一个线程访问。
3、 同步的局限性:导致程序的执行效率要降低
同步方法(非静态的)的锁为this。
同步方法(静态的)的锁为当前类本身。
class Singleton {private static Singleton instance = null;private Singleton() {}public static Singleton getInstance() {if (instance == null) {synchronized (Singleton.class) {if (instance == null) {instance = new Singleton();}}}return instance;}}public class TestSingleton {public static void main(String[] args) {Singleton s1 = Singleton.getInstance();Singleton s2 = Singleton.getInstance();System.out.println(s1 == s2);}}
小结:释放锁的操作
1、当前线程的同步方法、同步代码块执行结束
2、当前线程在同步代码块、同步方法中遇到break、return终止了该代码块、该方法的继续执行。
3、当前线程在同步代码块、同步方法中出现了未处理的Error或Exception,导致异常结束
4、当前线程在同步代码块、同步方法中执行了线程对象的wait()方法,当前线程暂停,并释放锁。
线程的死锁问题
l 死锁
不同的线程分别占用对方需要的同步资源不放弃,都在等待对方放弃自己需要的同步资源,就形成了线程的死锁
l 解决方法
1、专门的算法、原则
2、尽量减少同步资源的定义
public class TestDeadLock {public static void main(String[] args) {final StringBuffer s1 = new StringBuffer();final StringBuffer s2 = new StringBuffer();new Thread() {public void run() {synchronized (s1) {s2.append("A");synchronized (s2) {s2.append("B");System.out.print(s1);System.out.print(s2);}}}}.start();new Thread() {public void run() {synchronized (s2) {s2.append("C");synchronized (s1) {s1.append("D");System.out.print(s2);System.out.print(s1);}}}}.start();}}
声明:本文部分素材转载自互联网,如有侵权立即删除 。
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需!
7. 如遇到加密压缩包,请使用WINRAR解压,如遇到无法解压的请联系管理员!
8. 精力有限,不少源码未能详细测试(解密),不能分辨部分源码是病毒还是误报,所以没有进行任何修改,大家使用前请进行甄别
丞旭猿论坛
暂无评论内容