美文网首页
Android 多线程之synchronized锁住的是代码还是

Android 多线程之synchronized锁住的是代码还是

作者: 有没有口罩给我一个 | 来源:发表于2019-03-04 00:43 被阅读0次

    Android 线程简单分析(一)
    Android 并发之synchronized锁住的是代码还是对象(二)
    Android 并发之CountDownLatch、CyclicBarrier的简单应用(三)
    Android 并发HashMap和ConcurrentHashMap的简单应用(四)(待发布)
    Android 并发之Lock、ReadWriteLock和Condition的简单应用(五)
    Android 并发之CAS(原子操作)简单介绍(六)
    Android 并发Kotlin协程的重要性(七)(待发布)
    Android 并发之AsyncTask原理分析(八)(待发布)
    Android 并发之Handler、Looper、MessageQueue和ThreadLocal消息机制原理分析(九)
    Android 并发之HandlerThread和IntentService原理分析(十)

    在java中多线程并发时,多个线程同时请求一个共享资源,必然会导致此资源的数据不安全,可能我们就需要synchronized同步避免线程并发访问共享资源导致数据不安全,但是synchronized锁住的是代码还是对象?

    看一下栗子:

    public class SynchronizedExample {
    
     public synchronized void share() {
        Log.e("tag", "share 开始执行.....");
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        Log.e("tag", "share 结束.....");
        }
    }
    
      class SynchronizedExampleThread extends Thread {
        @Override
        public void run() {
            SynchronizedExample example = new SynchronizedExample();
            example.share();
        }
    }
    

    1、在SynchronizedExample 的share方法加synchronized 打印结果:

    share 开始执行.....
    share 开始执行.....
    share 开始执行.....
    share 结束.....
    share 结束.....
    share 结束.....
    

    可以看出来,上面的起动了三个线程,同时运行SynchronizedExample 类中的share方法,虽然share方法加上了synchronized,但是还是同时运行起来,好像synchronized并没起到同步的这用作用?

    再来改改,改成同步代码块?

     public void share() {
        synchronized (this) {
            Log.e("tag", "share 开始执行.....");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            Log.e("tag", "share 结束.....");
        }
    } 
    

    结果还是和上面的一样

    share 开始执行.....
    share 开始执行.....
    share 开始执行.....
    share 结束.....
    share 结束.....
    share 结束.....
    

    在java中,synchronized(this)以及非static的synchronized方法,只能防止多个线程同时执行同一个对象的同步代码段,即同一个锁监视器。
    分析一下上面的代码?

    实际上,在java中,对于非static的synchronized方法或者是synchronized代码块,锁的就是对象本身也就是this。是不是有答案了?

    synchronized锁住的是括号里的对象,而不是代码。

    当synchronized锁住一个对象后,别的线程如果也想拿到这个对象的锁,就必须等待(同步队列)这个线程执行完成释放锁,才能再次给对象加锁,这样才达到线程同步的目的,如果不明白可以看Android 线程简单分析(一)介绍,很详细。

    所以我们在用synchronized关键字的时候,能缩小代码段的范围就尽量缩小,能在代码段上加同步就不要再整个方法上加同步。这叫减小锁的粒度,使代码更大程度的并发。锁的代码段太长了,别的线程是不是要等很久。

    再看上面的代码,每个线程中都new了一个SynchronizedExample 类的对象,也就是产生了三个SynchronizedExample 对象,由于不是同一个对象,所以可以多线程同时运行synchronized方法或代码段。

    验证:

     SynchronizedExample example = new SynchronizedExample();
    class SynchronizedExampleThread extends Thread {
        @Override
        public void run() {
            example.share();
        }
    }
    

    结果:

     share 开始执行.....
     share 结束.....
     share 开始执行.....
     share 结束.....
     share 开始执行.....
     share 结束.....
    

    synchronized就起了作用。

    为了在明确一点我在创建两个SynchronizedExample 对象:

      SynchronizedExample example = new SynchronizedExample();
      SynchronizedExample example2 = new SynchronizedExample();
    
    class SynchronizedExampleThread extends Thread {
        @Override
        public void run() {
            example.share();
        }
    }
    
    class SynchronizedExampleThread2 extends Thread {
        @Override
        public void run() {
            example2.share2();
        }
    }
    

    结果:

    share 开始执行.....
    share2 开始执行.....
    share 结束.....
    share 开始执行.....
    share2 结束.....
    share2 开始执行.....
    share 结束.....
    share 开始执行.....
    share2 结束.....
    share2 开始执行.....
    share 结束.....
    share2 结束.....
    

    明显同一个所得是同一个对象,即同一把锁。

    未命名文件.png
    • 同一个对象每条线程进入同步代码块,其他线程将进入同步队列或锁池中等待其他线程释放锁,synchronize属于非公平锁,在锁池的等待的线程在线程1释放锁开始竞争锁,所以synchronize锁的是对象。

    • 非公平锁和公平锁
      1、非公平锁:线程加锁时直接尝试获取锁,获取不到就自动到队尾等待,ReentrantLock(默认)和synchronize属于非公平锁。
      2、公平锁:加锁前先查看是否有排队等待的线程,有的话优先处理排在前面的线程,先来先得。

    • 乐观锁和悲观锁
      1、悲观锁:假设一定会发生并发冲突,通过阻塞其他所有线程来保证数据的完整性,就是属于悲观主义,synchronize就是悲观锁。
      2、乐观锁:假设不会发生并发冲突,直接不加锁去完成某项更新,如果冲突就返回失败,CAS机制属于乐观的。

    相关文章

      网友评论

          本文标题:Android 多线程之synchronized锁住的是代码还是

          本文链接:https://www.haomeiwen.com/subject/nnpxuqtx.html