Android 线程及线程安全(二)之Synchronized vs Lock

Android 线程及线程安全(二)之Synchronized vs Lock

一、Synchronized

synchronized用于修饰方法、静态方法和代码块。

1、修饰代码块
    class SaleRunnable implements Runnable{
         private int tickets = 100;

        @Override
        public void run(){
            synchronized (this){
                while(tickets > 0){
                    Log.d("TicketsActivity"," 售出票号:"+tickets+"  thread.id=="+Thread.currentThread().getId());
                    try{
                        //假设售出一张票需要1s
                        Thread.sleep(1000);
                    }catch(Exception e){
                        Log.d("TicketsActivity","error="+e);
                    }
                    tickets --;
                }
                Log.e("TicketsActivity", "run: currentThread.id="+Thread.currentThread().getId());
            }

        }
    }

结果打印如下:
在这里插入图片描述
修饰代码块时,锁的作用范围为该类的实例对象,也就是上述的mSaleRunnable,这也解释了为什么312的线程没有进循环,是因为此时的tickets经过311线程的执行变成了0,所以不进循环内。此时被锁的对象是SaleRunnable的实例对象。但当Activity的onCreate()改为以下代码:

@Override
    protected void onCreate(Bundle savedInstanceState){
        Log.d("TicketsActivity", "onCreate: ");
        super.onCreate(savedInstanceState);
        new Thread(new SaleRunnable()).start();
        new Thread(new SaleRunnable()).start();
    }

结果打印如下:
在这里插入图片描述synchronized好像没有起作用,实际不是,synchronized是作用于类的实例对象,但是指针对单一对象,不能作用于实例对象与实例对象之间。上述已经是实例对象与实例对象了。
如果将synchronized 后跟的this改为SaleRunnable.class,如下:

private SaleRunnable mSaleRunnable;
    @Override
    protected void onCreate(Bundle savedInstanceState){
        Log.d("TicketsActivity", "onCreate: ");
        super.onCreate(savedInstanceState);
        mSaleRunnable = new SaleRunnable();
        new Thread(new SaleRunnable()).start();
        new Thread(new SaleRunnable()).start();
    }
      class SaleRunnable implements Runnable{
         private  int  tickets = 10;

        @Override
        public void run(){
            synchronized (SaleRunnable.class){
                while(tickets > 0){
                    Log.d("TicketsActivity"," 售出票号:"+tickets+"  thread.id=="+Thread.currentThread().getId());
                    try{
                        //假设售出一张票需要1s
                        Thread.sleep(1000);
                    }catch(Exception e){
                        Log.d("TicketsActivity","error="+e);
                    }
                    tickets --;
                }
                Log.e("TicketsActivity", "run: currentThread.id="+Thread.currentThread().getId());
            }
        }
    }

打印结果如下:
在这里插入图片描述
这里会进入两次循环,但是不会出现两个线程同时执行的情况,所以还是线程同步的,进入两次循环是因为有两个SaleRunnable的实例化对象,此时锁的作用范围是SaleRunnable类。

2、修饰方法

上述代码修改为:

    class SaleRunnable implements Runnable{
         private int tickets = 100;

        @Override
        public void run(){
            setTickets();
        }

        private synchronized void setTickets(){
            while(tickets > 0){
                Log.d("TicketsActivity"," 售出票号:"+tickets+"  thread.id=="+Thread.currentThread().getId());
                try{
                    //假设售出一张票需要1s
                    Thread.sleep(1000);
                }catch(Exception e){
                    Log.d("TicketsActivity","error="+e);
                }
                tickets --;
            }
            Log.e("TicketsActivity", "run: currentThread.id="+Thread.currentThread().getId());
        }
    }

与修饰代码块的打印结果一致,锁的作用范围为该类的实例对象,且不能作用于实例对象与实例对象之间。此时被称为对象实例锁。

3.修饰静态方法:
   static class SaleRunnable implements Runnable{
         private static int  tickets = 100;

        @Override
        public void run(){
            setTickets();
        }

        private synchronized static void setTickets(){
            while(tickets > 0){
                Log.d("TicketsActivity"," 售出票号:"+tickets+"  thread.id=="+Thread.currentThread().getId());
                try{
                    //假设售出一张票需要1s
                    Thread.sleep(1000);
                }catch(Exception e){
                    Log.d("TicketsActivity","error="+e);
                }
                tickets --;
            }
            Log.e("TicketsActivity", "run: currentThread.id="+Thread.currentThread().getId());
        }
    }

修饰静态方法时,锁的作用范围更广,不仅线程执行的是同一个SaleRunnable实例对象时线程同步,当不是同一个SaleRunnable实例对象时也能线程同步,打印结果与修饰方法块时一致。此时被锁的对象是SaleRunnable类。

二、Lock锁的使用
public class MultiThreadStu extends AppCompatActivity {
    private SaleRunnable mSaleRunnable;
    @Override
    protected void onCreate(Bundle savedInstanceState){
        Log.d("TicketsActivity", "onCreate: ");
        super.onCreate(savedInstanceState);
        mSaleRunnable = new SaleRunnable();
        new Thread(mSaleRunnable).start();
        new Thread(mSaleRunnable).start();

    }
    class SaleRunnable implements Runnable{
        private int tickets = 100;
        private Lock lock = new ReentrantLock();
        @Override
        public void run(){
            lock.lock();
            while(tickets > 0){
                Log.d("TicketsActivity"," 售出票号:"+tickets+"  thread.id=="+Thread.currentThread().getId());
                try{
                    //假设售出一张票需要1s
                    Thread.sleep(1000);
                }catch(Exception e){
                    Log.d("TicketsActivity","error="+e);
                }
                tickets --;
            }
            Log.e("TicketsActivity", "run: currentThread.id="+Thread.currentThread().getId());
            lock.unlock();
        }
    }
}

打印结果:
在这里插入图片描述
当修改onCreate的代码如下时:

protected void onCreate(Bundle savedInstanceState){
        Log.d("TicketsActivity", "onCreate: ");
        super.onCreate(savedInstanceState);
        mSaleRunnable = new SaleRunnable();
        new Thread(new SaleRunnable()).start();
        new Thread(new SaleRunnable()).start();

    }

打印结果如下:
在这里插入图片描述
这说明此时锁的作用范围是SaleRunnable的实例对象,而不是作用于SaleRunnable的实例对象与实例对象之间。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值