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 结束.....

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

Android 多线程之synchronized锁住的是代码还是对象(二)_第1张图片 未命名文件.png
  • 同一个对象每条线程进入同步代码块,其他线程将进入同步队列或锁池中等待其他线程释放锁,synchronize属于非公平锁,在锁池的等待的线程在线程1释放锁开始竞争锁,所以synchronize锁的是对象。

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

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

更多相关文章

  1. Android Handler机制5之Message简介与消息对象对象池
  2. Android——多线程
  3. input系统一 loop线程的创建与运行
  4. Android——导入已存在的android工程时出现红叉错误“AndroidMan
  5. AndroidUI线程机制
  6. android的大好时光结束进行时
  7. Android 对象序列化之你不知道的 Serializable
  8. Android 对象序列化之 Parcelable 取代 Serializable ?
  9. Android 对象序列化之追求完美的 Serial

随机推荐

  1. RXjava+Retrofit二级购物车
  2. 兔子--多击事件
  3. android音乐播放器Media
  4. 自定义的跑马灯控件
  5. Android跟随手指运动的小球 …
  6. Mediastreamer2
  7. 滴滴插件化框架学习笔记之virtualapk-gra
  8. 自定义Android(安卓)ORM 框架greenDAO数
  9. Android(安卓)Annotations 仿微博Tabbar
  10. 语音识别(加注释)