线程安全问题

来源:互联网 发布:月饼事件 知乎 编辑:程序博客网 时间:2024/05/31 18:30
/* 需求: 模拟3个窗口同时在售50张 票 。 问题1 :为什么50张票被卖出了150次?出现 的原因: 因为num是非静态的,非静态的成员变量数据是在每个对象中都会维护一份数据的,三个线程对象就会有三份。解决方案:把num票数共享出来给三个线程对象使用。使用static修饰。问题2: 出现了线程安全问题 ?线程 安全问题的解决方案:sun提供了线程同步机制让我们解决这类问题的。        java线程同步机制的方式:            方式一:同步代码块                        同步代码块的格式:                                synchronized(锁对象){                    需要被同步的代码...                }同步代码块要注意事项:        1. 任意的一个对象都可以做为锁对象。        2. 在同步代码块中调用了sleep方法并不是释放锁对象的。        3. 只有真正存在线程安全问题的时候才使用同步代码块,否则会降低效率的。        4. 多线程操作的锁 对象必须是 唯一共享的。否则无效。
 synchronized (new Object()) { } 无效
synchronized ("锁") { } 有效,
"锁"被创建后,不会再被创建了。
5. 一个线程在同步代码块中sleep了,并不会释放锁对象。

           6. 如果不存在着线程安全问题,千万不要使用同步代码块,因为会降低效率。


出现线程安全问题的根本原因: 1. 存在两个或者两个以上 的线程对象,而且线程之间共享着一个资源。 2. 有多个语句(两句及以上)操作了共享资源。(执行到一半,cpu执行权被抢走)
*/class SaleTicket extends Thread{ static int num = 50;//票数 非静态的成员变量,非静态的成员变量数据是在每个对象中都会维护一份数据的。 static Object o = new Object(); public SaleTicket(String name) { super(name); } @Override public void run() { while(true){ //同步代码块 synchronized ("锁") { if(num>0){ System.out.println(Thread.currentThread().getName()+"售出了第"+num+"号票"); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } num--; }else{ System.out.println("售罄了.."); break; } } } } } public class Demo4 { public static void main(String[] args) { //创建三个线程对象,模拟三个窗口 SaleTicket thread1 = new SaleTicket("窗口1"); SaleTicket thread2 = new SaleTicket("窗口2"); SaleTicket thread3 = new SaleTicket("窗口3"); //开启线程售票 thread1.start(); thread2.start(); thread3.start(); }}

 

如果采用第二种方式创建多线程,则不用static修饰num。因为只传了一个对象。

class SaleTicket implements Runnable{        int  num = 50; // 票数        @Override    public void run() {        while(true){            synchronized ("锁") {                if(num>0){                    System.out.println(Thread.currentThread().getName()+"售出了第"+ num+"号票");                    num--;                }else{                    System.out.println("售罄了..");                    break;                }                }        }            }}public class Demo4 {        public static void main(String[] args) {        //创建了一个Runnable实现类的对象        SaleTicket saleTicket = new SaleTicket();        //创建三个线程对象模拟三个窗口        Thread thread1 = new Thread(saleTicket,"窗口1");        Thread thread2 = new Thread(saleTicket,"窗口2");        Thread thread3 = new Thread(saleTicket,"窗口3");        //开启线程售票        thread1.start();        thread2.start();        thread3.start();    }}

 

0 0
原创粉丝点击