java线程安全

什么是线程安全问题?

当多个线程共享同一个全局变量,修改的时候,可能会受到其他线程干扰,导致数据有问题,这就现象叫做线程安全问题。读的时候,不会产生线程安全问题

多个线程共享一个局部变量,对变量修改时不会对发生线程安全问题

 

示例:车站卖票经典案例

public class ThreadDemo implements Runnable {
    //一共有一百张票
    private int count = 100;

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

    private void sale() {
        if (count > 0) {
            System.out.println(Thread.currentThread().getName() + "出售第" + (100 - count + 1) + "张票");
            count--;
        }
    }

    public static void main(String[] args) {
        ThreadDemo threadDemo = new ThreadDemo();
        Thread t1 = new Thread(threadDemo, "窗口1");
        Thread t2 = new Thread(threadDemo, "窗口2");
        t1.start();
        t2.start();
    }
}

观察输出发现很多重复票出售。

 

如何解决线程安全问题?

synchroizcd    --手动锁

lock  --jdk1.5并发包 --手动

 

使用synchroizcd解决线程安全问题

private synchronized void sale() {
        if (count > 0) {
            System.out.println(Thread.currentThread().getName() + "出售第" + (100 - count + 1) + "张票");
            count--;
        }
    }

 

原理:
1、对一段代码块加锁了之后,当第一个线程执行到这段加锁的代码块后就会先拿到一个锁,这时其他线程就不能执行这段加锁的代码块了,会在外面等待。因为锁已经被另一个线程拿到了,只有拿到锁的线程才能执行这段加锁的代码块,当第一个拿到锁的线程把锁释放后,这时其他线程就可以去抢这把锁了,当有一个线程抢到锁后,其他线程就只能继续等待锁释放。

2、锁是什么时候释放?代码执行完毕或者是程序抛出异常锁都会被释放

3、锁已经被释放的话,其他线程开始抢这把锁,执行同步代码块

 

什么地方需要考虑加锁?

1.有两个线程以上,需要发生同步

2.多个线程想同步,必须要用同意把锁。

3.保证同一时刻只有一个线程进行执行。

好处:解决了多线程的安全问题 

弊端:多个线程需要判断锁,较为消耗资源、抢锁的资源。

 

什么是同步代码块?

就是将可能会发生线程安全问题的代码,给包括起来

synchronized(同一个对象){
    //可能会发生线程冲突问题
}

对象如同锁,持有锁的线程可以在同步中执行 

 

 

同步函数:就是在方法上加上 synchronized

同步函数 使用什么锁?  this锁。

一个线程使用同步代码块(this明锁),另一个线程使用同步函数。如果两个线程抢票不能实现同步,那么会出现数据错误。

 

 

静态同步函数

 

方法上加上static关键字,使用synchronized 关键字修饰 或者使用类.class文件。

 

静态的同步函数使用的锁是  该函数所属字节码文件对象

 

可以用 getClass方法获取,也可以用当前  类名.class 表示。

 

 

多线程死锁问题:

 

产生场景:初学者喜欢每个地方都加入synchronized,于是synchronized中嵌套synchronized,容易产生死锁

 

产生原因:A线程拿到了锁2,现在需要拿锁1;B线程拿了锁1,现在需要拿锁2;A线程拿不到锁1就不会释放锁2;B线程拿不到锁2就不会释放锁1

你可能感兴趣的:(java线程安全)