Java 之线程安全

   一.线程安全       二.解决线程安全       1.使用同步代码块    2.使用同步方法    3.静态方法        4.使用Lock锁

    线程优先级         jion         yield          守护线程                线程死锁

一.线程安全

        RunnableImpl run = new RunnableImpl();
        Thread t0 = new Thread(run);
        Thread t1 = new Thread(run);
        Thread t2 = new Thread(run);
        t0.start();
        t1.start();
        t2.start();

    当创建多个线程操作同一个 实现类时,由于数据是共享的 ,一个线程可能会 执行run方法时被其他线程抢到,权限

    第一个线程还没有操作完 ,而第二个线程又到来了  操作这个数据  就可能发生混乱

二.解决线程安全

   1.使用同步代码块 

         1.通过代码块中的锁对象,可以使用任意的对象

         2.但是必须保证多个线程使用的锁对象是同一个

         3.锁对象作用: 把同步代码块锁住,只让一个线程在同步代码块中执行

        synchronized(锁对象){
            可能会出现线程安全问题的代码(访问了共享数据的代码)
        }
public class RunnableImpl implements Runnable{
    private  int ticket = 100; 
    Object obj = new Object();           //创建一个锁对象 可以是随意的 同步锁
    @Override
    public void run() {
        while(true){
            synchronized (obj){                  //同步代码块
                if(ticket>0){
                    System.out.println(Thread.currentThread().getName()+"-->正在卖第"+ticket+"张票");
                    ticket--;
                }
            }

      原理: 当t1线程抢到执行权时,会检查synchronized  代码块 是否有 锁对象,发现有就会获取到锁对象,进入到同步中执行.

      这时当t2抢到执行权时,遇到synchronized 代码块会继续检查,发现没有就会阻塞,直到t1执行完锁对象才被归还,t2才能又获取          锁对象进入代码块执行.   一句话: 同步中的线程,没有执行完毕不会释放锁,同步外的线程没有锁对象进不去代码块

      缺点: 频繁的判断锁,释放锁获取锁,效率降低

2.使用同步方法

public class Syn implements Runnable{
    private  int ticket = 100; 
    @Override
    public void run() {
        while(true){
        pay();
    }
}
public synchronized void pay() {
        if (num > 0) {
            System.out.println(Thread.currentThread().getName() + "-->正在卖第" + num + "张票");
            num--;
        }
    }


        Syn syn = new Syn();
        System.out.println(syn);
        Thread t1 = new Thread(syn);
        Thread t2 = new Thread(syn);
        Thread t3 = new Thread(syn);
        t1.start();
        t2.start();
        t3.start();

       原理就是锁对象就是 this    实现Runnable类的对象 syn   

        所以第一种方法不用创建一个对象同步代码块 传入this也可以

  3.静态方法

public class Syn implements Runnable {
public static void payTicketStatic(){
        synchronized (Syn.class){     静态方法不能使用this  本类的class文件对象也可以
            if(ticket>0){
                System.out.println(Thread.currentThread().getName()+"-->正在卖第"+ticket+"张票");
                ticket--;
            }
        }}}

4.使用Lock锁

 1.在可能会出现安全问题的代码前调用Lock接口中的方法lock获取锁

 2.在可能会出现安全问题的代码后调用Lock接口中的方法unlock释放锁

public class LockDemo implements Runnable {
    private int num = 100;
    Lock l = new ReentrantLock();
    @Override
    public void run() {
        while (true){
            l.lock();
            if(num > 0){
                try {
                    Thread.sleep(10);
                    System.out.println(Thread.currentThread().getName()+"--正在卖第"+num+"票");
                    num--;
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }finally {
                    l.unlock();
                    System.out.println(l);}}}

        LockDemo lockDemo = new LockDemo();
        Thread t= new Thread(lockDemo);
        Thread t1= new Thread(lockDemo);
        Thread t2= new Thread(lockDemo);
        t.start();
        t1.start();
        t2.start();

线程优先级

   1.每个线程的优先级默认是5   最高可以设置为10最低1        2.t.setPriority( 10)  这样也不是全执行它,只是执行几率更大

jion

  1.设置join 后会等待这个线程执行完,才执行其他的线程   与Python 类似       在start()  之后设置  t.join( )

yield

  1.在run方法内部,设置 Thread.yield() ;    作用为 让出cpu执行权 ,进入就绪状态,还可以抢夺资源

守护线程

 1.     t.setDaemon(true);   在start之前设置  作用为 这个线程随着出线程的结束而结束  

线程死锁

  1.当有两个线程,他们都是同步的,  当t1 拿到一把锁lock1  ,t2拿到一把锁lock2      这时t1还想拿锁lock2  t2还想拿锁lock1

    这样它们就会僵住,称为线程死锁.

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值