编程语言
首页 > 编程语言> > java线程安全初窥探

java线程安全初窥探

作者:互联网


java 同步函数

首先看一下问题场景

package com.Thread.Test;

/**
 * 抢票问题的一个案例分析
 */

class ThreadTrain implements Runnable{

    private int TrainCount = 100;


    @Override
    public void run() {
            while (TrainCount>0){
                try {
                    Thread.sleep(50);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                sale();
            }
    }

    private void sale(){
        System.out.println(Thread.currentThread().getName()+":正在出售第"+(100-TrainCount+1)+"张票");
        TrainCount--;
    }
}


public class Main {

    public static void main(String[] args) {
    //开辟两个线程
        ThreadTrain threadTrain = new ThreadTrain();
        Thread t1 = new Thread(threadTrain, "窗口一");
        Thread t2 = new Thread(threadTrain, "窗口二");

        t1.start();

        t2.start();

    }
}

Console :
Console :
可以看到 上图 会出现两个线程同时贩卖一张票的情况,而且最后会出现贩卖101张票的时候

synchronize 解决代码:

package com.Thread.Test;

/**
 * 抢票问题的一个案例分析
 */

class ThreadTrain implements Runnable{

    private int TrainCount = 100;


    @Override
    public void run() {
        while (TrainCount>0){
            try {
                Thread.sleep(50);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            sale();
        }
    }

    //synchronized 分成 函数 和标识两个  
    private synchronized void sale(){ //this锁
//        synchronized (this){
        //加一个判断 判断最后一张票的两个线程情况
        if(TrainCount>0){
            System.out.println(Thread.currentThread().getName()+":正在出售第"+(100-TrainCount+1)+"张票");
            TrainCount--;
        }

//        }
    }
}


public class Main {

    public static void main(String[] args) {
        ThreadTrain threadTrain = new ThreadTrain();
        Thread t1 = new Thread(threadTrain, "窗口一");
        Thread t2 = new Thread(threadTrain, "窗口二");

        t1.start();

        t2.start();

    }
}

synchronize 方法 比较方便,但是拓展性不高,资源占用大

lock锁的解决办法

package com.Thread.Test;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

class ThreadTrain implements Runnable{

    private int TrainCount = 100;
    private Lock lock = new ReentrantLock();

    @Override
    public void run() {

        while (TrainCount>0){
            try {
                Thread.sleep(50);
                sale();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    //synchronized 分成 函数 和标识两个
    private  void sale(){ //this锁

        try {
            lock.lock();
            if(TrainCount>0){
                System.out.println(Thread.currentThread().getName()+":正在出售第"+(100-TrainCount+1)+"张票");
                TrainCount--;
            }
        }catch (Exception e) {
            e.printStackTrace();
        }finally {
            lock.unlock();
        }

    }
}


public class LockTest {
    public static void main(String args[]) throws InterruptedException {
        ThreadTrain threadTrain = new ThreadTrain();
        Thread t1 = new Thread(threadTrain, "窗口一");
        Thread t2 = new Thread(threadTrain, "窗口二");

        t1.start();
        Thread.sleep(40);
        t2.start();
    }
}


result


java静态同步函数

private static synchronized void sale(){ //this锁
//        synchronized (this){
        //加一个判断 判断最后一张票的两个线程情况
        if(TrainCount>0){
            System.out.println(Thread.currentThread().getName()+":正在出售第"+(100-TrainCount+1)+"张票");
            TrainCount--;
        }

//        }
    }

是和下面的功能是一样的

 private  void sale(){ //this锁
        synchronized (ThreadTrain.class){
        //加一个判断 判断最后一张票的两个线程情况
        if(TrainCount>0){
            System.out.println(Thread.currentThread().getName()+":正在出售第"+(100-TrainCount+1)+"张票");
            TrainCount--;
        }

        }
    }

线程死锁

package com.Thread.Test;

/**
 * 抢票问题的一个案例分析
 */

class ThreadTrain implements Runnable{

    private int TrainCount = 100;

    private Object oj = new Object();

    public boolean flag = true;

    @Override
    public void run() {
        if(flag){
            while (TrainCount>0){

                synchronized (oj){
                    //加一个判断 判断最后一张票的两个线程情况
                    sale();

                }
            }
        }else{
            while(TrainCount>0){
                sale();
            }

        }

    }

    private synchronized void sale(){
        synchronized (oj){
        //加一个判断 判断最后一张票的两个线程情况
        if(TrainCount>0){
            try {
                Thread.sleep(40);
            } catch (Exception e) {

            }

            System.out.println(Thread.currentThread().getName()+":正在出售第"+(100-TrainCount+1)+"张票");
            TrainCount--;
        }

        }
    }
}

public class Main {

    public static void main(String[] args) throws InterruptedException {
        ThreadTrain threadTrain = new ThreadTrain();
        Thread t1 = new Thread(threadTrain, "窗口一");
        Thread t2 = new Thread(threadTrain, "窗口二");

        t1.start();
        Thread.sleep(40);
        threadTrain.flag = false;
        t2.start();

    }
}

运行结果

产生原因: 一个线程已经占用了Object锁之后,打算进入this锁。但是第二个线程从flag = false那里的代码块直接占用this锁,从而第一个线程进不去sale()方法,而第二个方法执行sale()方法需要解开Object锁,导致死锁的产生。
这就好比是两个好友分别有对方的密码盒,并且都有自己钥匙,但是都不会把钥匙给对方,从而会产生一个谁也打不就开密码盒的尴尬情况。

标签:java,Thread,TrainCount,void,窥探,线程,new,public
来源: https://www.cnblogs.com/adroitwolf/p/14309953.html