Android学习:线程同步之synchronized

来源:互联网 发布:淘宝店铺氛围图是什么 编辑:程序博客网 时间:2024/05/23 14:18

  synchronized:Java语言的关键字,当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码。

    一、当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。

    二、然而,当一个线程访问object的一个synchronized(this)同步代码块时,另一个线程仍然可以访问该object中的非synchronized(this)同步代码块。

    三、尤其关键的是,当一个线程访问object的一个synchronized(this)同步代码块时,其他线程对object中所有其它synchronized(this)同步代码块的访问将被阻塞。

    四、第三个例子同样适用其它同步代码块。也就是说,当一个线程访问object的一个synchronized(this)同步代码块时,它就获得了这个object的对象锁。结果,其它线程对该object对象所有同步代码部分的访问都被暂时阻塞。

    五、以上规则对其它对象锁同样适用.

举例说明: 

   一、当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。

package com.tongseng.threadlock;import android.util.Log;/** * Created by tongseng on 2017/8/31. * e-mail:tongseng.wu@qq.com * Function: */public class ThreadLock_Parallel implements Runnable{    @Override    public void run() {        synchronized (this){            for (int i = 0; i < 3; i++) {                try {                    Thread.sleep(500);                }catch (InterruptedException e){                    e.printStackTrace();                }                Log.d("ThreadLock_Parallel:", Thread.currentThread().getName() + " synchronized loop " + i);            }        }    }}

在Activity中同时创建两个线程,并同时去执行该线程:

    private void ThreadLockParallelShow(){        ThreadLock_Parallel lock_parallel = new ThreadLock_Parallel();        Thread thread01 = new Thread(lock_parallel,"A");        Thread thread02 = new Thread(lock_parallel,"B");        thread01.start();        thread02.start();    }
查看执行结果:

01-03 19:55:05.692 11476-11476/com.tongseng.threadlock D/ThreadLock: Welcome to  tongseng's Blog!
                                                                   synchronized key word
                                                                   ----------------------
01-03 19:55:06.194 11476-11520/com.tongseng.threadlock D/ThreadLock_Parallel:: A synchronized loop 0
01-03 19:55:06.695 11476-11520/com.tongseng.threadlock D/ThreadLock_Parallel:: A synchronized loop 1
01-03 19:55:07.195 11476-11520/com.tongseng.threadlock D/ThreadLock_Parallel:: A synchronized loop 2
01-03 19:55:07.696 11476-11521/com.tongseng.threadlock D/ThreadLock_Parallel:: B synchronized loop 0
01-03 19:55:08.196 11476-11521/com.tongseng.threadlock D/ThreadLock_Parallel:: B synchronized loop 1
01-03 19:55:08.697 11476-11521/com.tongseng.threadlock D/ThreadLock_Parallel:: B synchronized loop 2
看到,只有A线程执行完成之后才回去执行B线程。

二、然而,当一个线程访问object的一个synchronized(this)同步代码块时,另一个线程仍然可以访问该object中的非synchronized(this)同步代码块。

package com.tongseng.threadlock;import android.util.Log;/** * Created by tongseng on 2017/8/31. * e-mail:tongseng.wu@qq.com * Function: */public class ThreadLock_UnParallel {    public void method01() {        synchronized(this) {            int i = 3;            while( i-- > 0) {                Log.d("ThreadLock_UnParallel", Thread.currentThread().getName() + " : " + i);                try {                    Thread.sleep(500);                } catch (InterruptedException ie) {                }            }        }    }    /**     * 当一个线程访问object的一个synchronized(this)同步代码块时,     * 另一个线程仍然可以访问该object中的非synchronized(this)同步代码块。     */    public void method02() {        int i = 3;        while( i-- > 0) {            Log.d("ThreadLock_UnParallel", Thread.currentThread().getName() + " : " + i);            try {                Thread.sleep(300);            } catch (InterruptedException ie) {            }        }    }}
在Activity中同时创建两个线程,并同时去执行该线程:

    private void ThreadLockUnParallelShow(){        final ThreadLock_UnParallel lock_unParallel = new ThreadLock_UnParallel();        Thread thread01 = new Thread(new Runnable() {            @Override            public void run() {                lock_unParallel.method01();            }        }, "A");        Thread thread02 = new Thread(new Runnable() {            @Override            public void run() {                lock_unParallel.method02();            }        },"B");        thread01.start();        thread02.start();    }
查看执行结果:

01-03 20:01:00.059 16589-16589/? D/ThreadLock: Welcome to  tongseng's Blog!
                                               synchronized key word
                                               ----------------------
01-03 20:01:00.061 16589-16606/? D/ThreadLock_UnParallel: B : 2
01-03 20:01:00.061 16589-16605/? D/ThreadLock_UnParallel: A : 2
01-03 20:01:00.362 16589-16606/? D/ThreadLock_UnParallel: B : 1
01-03 20:01:00.561 16589-16605/? D/ThreadLock_UnParallel: A : 1
01-03 20:01:00.662 16589-16606/? D/ThreadLock_UnParallel: B : 0
01-03 20:01:01.062 16589-16605/? D/ThreadLock_UnParallel: A : 0

可以看到,A线程在synchronize之后B线程也是同时执行的,并没有因为A线程被加锁就导致阻塞。

   三、尤其关键的是,当一个线程访问object的一个synchronized(this)同步代码块时,其他线程对object中所有其它synchronized(this)同步代码块的访问将被阻塞。

public class ThreadLock {    public void method01() {        synchronized (this) {            int i = 0;            while (i++ < 3) {                Log.d("ThreadLock", Thread.currentThread().getName() + ":" + i);                try {                    Thread.sleep(500);                } catch (InterruptedException e) {                    e.printStackTrace();                }            }        }    }    /**     * 当一个线程访问object的一个synchronized(this)同步代码块时,     * 其他线程对object中所有其它synchronized(this)同步代码块的访问将被阻塞。     */    public void method02() {        synchronized (this) {            int j = 0;            while (j++ < 3) {                Log.d("ThreadLock", Thread.currentThread().getName() + ":" + j);                try {                    Thread.sleep(500);                } catch (InterruptedException e) {                    e.printStackTrace();                }            }        }    }
在Activity中同时创建两个线程,并同时去执行该线程:

    private void ThreadLockShow(){        final ThreadLock lock = new ThreadLock();        Thread thread01 = new Thread(new Runnable() {            @Override            public void run() {                lock.method01();            }        },"A");        Thread thread02 = new Thread(new Runnable() {            @Override            public void run() {                lock.method02();            }        },"B");        thread01.start();        thread02.start();    }
执行结果如下:

01-03 20:10:12.895 24398-24398/? D/ThreadLock: Welcome to  tongseng's Blog!
                                               synchronized key word
                                               ----------------------
01-03 20:10:12.898 24398-24414/com.tongseng.threadlock D/ThreadLock: A:1
01-03 20:10:13.398 24398-24414/com.tongseng.threadlock D/ThreadLock: A:2
01-03 20:10:13.899 24398-24414/com.tongseng.threadlock D/ThreadLock: A:3
01-03 20:10:14.399 24398-24415/com.tongseng.threadlock D/ThreadLock: B:1
01-03 20:10:14.900 24398-24415/com.tongseng.threadlock D/ThreadLock: B:2 
01-03 20:10:15.400 24398-24415/com.tongseng.threadlock D/ThreadLock: B:3

四、第三个例子同样适用其它同步代码块。也就是说,当一个线程访问object的一个synchronized(this)同步代码块时,它就获得了这个object的对象锁。结果,其它线程对该object对象所有同步代码部分的访问都被暂时阻塞。

    /**     * 当一个线程访问object的一个synchronized(this)同步代码块时,     * 它就获得了这个object的对象锁。     * 结果,其它线程对该object对象所有同步代码部分的访问都被暂时阻塞。     */    public synchronized void method03(){        int k=0;        while(k++ < 3){            Log.d("ThreadLock", Thread.currentThread().getName() + ":" + k);            try {                Thread.sleep(500);            } catch (InterruptedException e) {                e.printStackTrace();            }        }    }
执行结果如下:

01-03 20:10:12.898 24398-24414/com.tongseng.threadlock D/ThreadLock: A:1
01-03 20:10:13.398 24398-24414/com.tongseng.threadlock D/ThreadLock: A:2
01-03 20:10:13.899 24398-24414/com.tongseng.threadlock D/ThreadLock: A:3
01-03 20:10:14.399 24398-24415/com.tongseng.threadlock D/ThreadLock: C:1
01-03 20:10:14.900 24398-24415/com.tongseng.threadlock D/ThreadLock: C:2 
01-03 20:10:15.400 24398-24415/com.tongseng.threadlock D/ThreadLock: C:3

也就是说,当一个线程访问object的一个synchronized(this)同步代码块时,他就获得了这个object的对象锁,那么,其它的线程对该object对象所有同步代码部分的访问都被暂时阻塞。

五、以上规则对其它对象锁同样适用:

package com.tongseng.threadlock;import android.util.Log;/** * Created by tongseng on 2017/8/31. * e-mail:tongseng.wu@qq.com * Function: */public class ThreadLock_InnerClass {    class Inner{        public void method01() {            int i = 3;            while(i-- > 0) {                Log.d("Inner", Thread.currentThread().getName() + " : Inner.method01()=" + i);                try {                    Thread.sleep(500);                } catch(InterruptedException ie) {                }            }        }        public void method02() {            /*synchronized (this)*/{                int i = 3;                while(i-- > 0) {                    Log.d("Inner", Thread.currentThread().getName() + " : Inner.method02()=" + i);                    try {                        Thread.sleep(300);                    } catch(InterruptedException ie) {                    }                }            }        }    }    public Inner getInnerInstance(){        return new Inner();    }}
调用的地方如下:

    private void ThreadLock_InnerClassShow(){        ThreadLock_InnerClass lock_innerClass = new ThreadLock_InnerClass();        final ThreadLock_InnerClass.Inner inner = lock_innerClass.getInnerInstance();        Thread thread01 = new Thread(new Runnable() {            @Override            public void run() {                if (inner != null) {                    synchronized (inner){                        inner.method01();                    }                }            }        },"A");        Thread thread02 = new Thread(new Runnable() {            @Override            public void run() {                if (inner != null) {                    inner.method02();                }            }        },"B");        thread01.start();        thread02.start();    }
执行结果:

尽管线程thread01获得了对Inner的对象锁,但由于线程thread02访问的是同一个Inner中的非同步部分。所以两个线程互不干扰。


    thread01 :Inner.method01()=2  
    thread02 :Inner.method02()=2  
    thread01 :Inner.method01()=1  
    thread02 :Inner.method02()=1  
    thread01 :Inner.method01()=0  
    thread02 : Inner.method02()=0

如果在method02也做了synchronized的话,那么就是A线程先执行完,然后再去执行B线程了。
原创粉丝点击