线程安全问题

Posted iFat的笔记本

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了线程安全问题相关的知识,希望对你有一定的参考价值。

/*
 需求: 模拟3个窗口同时在售50张 票 。
 
问题1 :为什么50张票被卖出了150次?

出现 的原因: 因为num是非静态的,非静态的成员变量数据是在每个对象中都会维护一份数据的,三个线程对象就会有三份。

解决方案:把num票数共享出来给三个线程对象使用。使用static修饰。

问题2: 出现了线程安全问题 ?

线程 安全问题的解决方案:sun提供了线程同步机制让我们解决这类问题的。
    
    java线程同步机制的方式:
    
        方式一:同步代码块
            
            同步代码块的格式:
                
                synchronized(锁对象){
                    需要被同步的代码...
                }

同步代码块要注意事项:
        1. 任意的一个对象都可以做为锁对象。
        2. 在同步代码块中调用了sleep方法并不是释放锁对象的。
        3. 只有真正存在线程安全问题的时候才使用同步代码块,否则会降低效率的。
        4. 多线程操作的锁 对象必须 是唯一共享 的。否则无效。
        

需求: 一个银行账户5000块,两夫妻一个拿着 存折,一个拿着卡,开始取钱比赛,每次只能取一千块,要求不准出现线程安全问题。
        
        
        
        方式二:同步函数

出现线程安全问题的根本原因:
    1. 存在两个或者两个以上 的线程对象,而且线程之间共享着一个资源。
    2. 有多个语句操作了共享资源。
    

 
 */

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();
        
    }
    
}

 

以上是关于线程安全问题的主要内容,如果未能解决你的问题,请参考以下文章

HashMap 和 ConcurrentHashMap 的区别

线程同步-使用ReaderWriterLockSlim类

newCacheThreadPool()newFixedThreadPool()newScheduledThreadPool()newSingleThreadExecutor()自定义线程池(代码片段

线程安全问题的概述和线程安全的代码实现与问题产生的原理

多线程 Thread 线程同步 synchronized

活动到片段方法调用带有进度条的线程