多线程安全

什么时候会出现线程安全问题?
1.存在多线程的情况
2.多个线程之间存在共享数据
3.存在多条语句操作共享数据

如何解决多线程安全问题?
注意:线程安全执行效率就低,线程不安全,执行效率高
A:同步代码块
synchronized(对象) {
需要被同步的代码}

以3个售票窗口卖票举例:

public class MyThread implements Runnable{

    int ticket=70;
    Object obj = new Object();  //此对象被用来当作锁
    @Override
    public void run() {
        // TODO Auto-generated method stub

        while(true){

            //当被同步的代码执行完毕之后,th1手里拿着的obj这个锁才会被释放,
            //th1,th2,th3重新抢占cpu的执行权,谁抢到了继续拿着obj这个锁,执行同步代码块中的内容

            synchronized (obj) {     //同步代码块,括号内的对象即锁
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                if(ticket>0){
                    System.out.println(Thread.currentThread().getName()+"正在出售第"+ticket--+"张票");
                }else{
                    break;
                }
            }

        }
    }

}

如果不是用同步代码块的话,上述代码会怎么样呢?

会出现几个窗口同时卖一张票的情况,原因就是当天th1进入while循环后,进入休眠,此时因为没有锁,所以th2也能进来,而此时ticket的值并没有自减。

B:同步方法
public synchronized void sellTicket(){同步代码}

public class MyThread implements Runnable{

    int ticket=70;
    @Override
    public void run() {
        // TODO Auto-generated method stub
        while(true){
            sellTicket();
            if(ticket<=0){
                break;
            }
        }
    }

    //同步方法是将synchronized关键字加到方法上,同步方法的锁是this
    private synchronized void sellTicket() {
        // TODO Auto-generated method stub
        if(ticket>0){
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+"正在出售第:"+ticket--+"张票");
        }
    }

}

C:静态同步方法
类的字节码对象
public static synchronized void sellTicket() {
需要同步的代码
}

public class MyThread implements Runnable{

    static int ticket=70;
    @Override
    public void run() {
        // TODO Auto-generated method stub
        while(true){
            sellTicket();
            if(ticket<=0){
                break;
            }
        }
    }

    //静态同步方法,他的锁是本类的字节码文件对象:类名.class
    private static synchronized void sellTicket() {
        // TODO Auto-generated method stub
        if(ticket>0){
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+"正在出售第:"+ticket--+"张票");

        }
    }

}

匿名内部类的方式使用多线程

public static void main(String[] args) {
        // TODO Auto-generated method stub
        new Thread(){
            public void run(){
                for(int i=0;i<50;i++){
                    System.out.println(i);
                }
            }
        }.start();

        new Thread(new Runnable() {

            @Override
            public void run() {
                // TODO Auto-generated method stub
                for(int i=0;i<50;i++){
                    System.out.println(i);
                }
            }
        }).start();
    }

JDK5的Lock锁,我们之前造的所有的锁都没有手动释放锁
static Lock lock = new ReentrantLock();
枷锁:lock.lock();
释放锁:lock.unlock();
可以让我们明确的知道在哪里加锁和释放锁。

public class MyThread implements Runnable{

    int ticket=70;
    //创建一个锁
    Lock lock = new ReentrantLock();

    @Override
    public void run() {
        // TODO Auto-generated method stub
        while(true){
            //上锁
            lock.lock();
            if(ticket>0){
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName()+"正在出售第"+ticket--+"张票");
                //释放锁
                lock.unlock();
            }else{
                lock.unlock();
                break;
            }
        }
    }

}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值