Java- 简单了解线程 同步线程和死锁(二)
例如上一篇的售票的例子,可能会打印出负数的票,主要的原因是由于线程之间的切换。要避免这个问题,必须在卖票的时候加一个限制,指定此时此刻只有等这个售票点卖完票,其他售票点才能卖票。
看一下出现问题的情况
public class test9 { public static void main(String[] args) { TestThread t = new TestThread(); new Thread(t).start(); new Thread(t).start(); new Thread(t).start(); new Thread(t).start(); } } class TestThread implements Runnable { int tickets = 100; //String str = new String(""); public void run() { while(true) { if(tickets>0) { try{ Thread.sleep(10);} catch(Exception e){} System.out.println(Thread.currentThread().getName() + "当前票数还有:" + tickets--); } } } }
解决方法一,加一个synchronized关键字。给synchronized里传一个对象,他相当于一个标志位,当执行synchronized语句后此处变为0,他运行结束后又会变成1。当他是0的情况,那么其他线程运行到此处时会被阻塞
public class test9 { public static void main(String[] args) { TestThread t = new TestThread(); new Thread(t).start(); new Thread(t).start(); new Thread(t).start(); new Thread(t).start(); } } class TestThread implements Runnable { int tickets = 100; String str = new String(""); public void run() { while(true) { synchronized(str) { if(tickets>0) { try{ Thread.sleep(10);} catch(Exception e){} System.out.println(Thread.currentThread().getName() + "当前票数还有:" + tickets--); } } } } }
解决方法二,进一步的写法
public class test9 { public static void main(String[] args) { TestThread t = new TestThread(); new Thread(t).start(); new Thread(t).start(); new Thread(t).start(); new Thread(t).start(); } } class TestThread implements Runnable { int tickets = 100; // String str = new String(""); public void run() { while(true) { sale(); } } public synchronized void sale() { if(tickets>0) { try{ Thread.sleep(10);} catch(Exception e){} System.out.println(Thread.currentThread().getName() + "当前票数还有:" + tickets--); } } }
线程死锁原因:造成线程死锁一般的主要原因是出现的环路,你调用我,我调用你。彼此都在等待对方,出现无止境的等待。
孙钟秀的操作系统教程里这么定义死锁:如果一个进程集合中的每个进程都在等待只能由此集合中的其他进程才能引发的事件,而无限期限入僵持的局面称为死锁。(省略其他一些文字,看黑色加粗部份会更好理解!)。虽然这个定义是对进程而言的,不对我想对线程同样适用。
例如下面的程序
View Code
class A { synchronized void foo(B b) { String name = Thread.currentThread().getName(); System.out.println(name + " entered A.foo "); Thread.sleep(1000): System.out.println(name + " trying to call B.last()"); b.last(); } synchronized void last() { //A.last } } class B { synchronized void bar(A a) { String name = Thread.currentThread().getName(); System.out.println(name + " entered B.bast "); Thread.sleep(1000): System.out.println(name + " trying to call a.last()"); a.last(); } synchronized void last() { //B.last } } class Deadlock implements Runnable { A a = new A(); B b = new B(); Deadlock() { new Thread(this).start(); a.foo(b); } public void run() { b.bar(a); } }