synchronized 关键字解析

由于同一进程的多个线程共享同一片内存存储空间,在带来方便的同时,也带来了访问冲突这个严重的问题。Java语言提供了专门的机制来解决这种冲突,有效的避免了同一个数据对象被多个线程同时访问。

需要明确的几个问题:
synchronized关键字可以作为方法的修饰符,也可以作为方法内的语句(即平时说的同步方法和同步代码块)如果再细分,其可以作用于instance(成员变量)、object reference(对象应用)、static(静态方法)和class literals(类名称字面常量)上
无论synchronized 关键字作用于方法还是对象上,他取得的锁都是对象锁
每个对象只有一个锁与之关联
实现同步需要很大的系统开销做为代价的,同步可能造成死锁,所以程序设计时应尽量避免使用无谓的同步控制

synchronized 作用域对比分析,案例代码如下:

package org.xyz.java.basic.keys;
import java.util.concurrent.TimeUnit;
/**
 * synchronized 关键字讲解
 * @author kevin.chen
 */
public class SynchronizedDemo {
        
        public static void main(String[] args) {
                /**
                 * a()和c()方法竞争同一把锁,对应Thread-0和Thread-2线程; 
                 * b()和d()方法竞争另外一把锁,对应Thread-1和main线程
                 	   Thread-0: synchronized in a()
                        Thread-0: synchronized in a() for -> 0
                        Thread-1: synchronized in b()
                        Thread-1: synchronized in b() for -> 0
                        main: not synchronized in d()
                        Thread-2: not synchronized in c()
                        Thread-1: synchronized in b() for -> 1
                        Thread-0: synchronized in a() for -> 1
                        Thread-0: synchronized in a() for -> 2
                        Thread-1: synchronized in b() for -> 2
                        Thread-0: synchronized in a() for -> 3
                        Thread-1: synchronized in b() for -> 3
                        Thread-0: synchronized in a() for -> 4
                        Thread-1: synchronized in b() for -> 4
                        Thread-2: synchronized in c() for -> 0
                        main: synchronized in d() for -> 0
                        main: synchronized in d() for -> 1
                        Thread-2: synchronized in c() for -> 1
                        Thread-2: synchronized in c() for -> 2
                        main: synchronized in d() for -> 2
                        Thread-2: synchronized in c() for -> 3
                        main: synchronized in d() for -> 3
                        Thread-2: synchronized in c() for -> 4
                        main: synchronized in d() for -> 4
                        main thread over
                 */
                Foo.doRun();
                
        }
}
/**
 * synchronized 作用于方法和作用于代码块的对比
 * @author kevin.chen
 */
class Foo {
        
        /**
         * synchronized 关键字修饰在类的静态方法中,此时线程调用该方法,
         * 需要获取的锁对象是类锁,相当于Foo.class
         */
        synchronized public static void a() {
                System.out.println(Thread.currentThread().getName() + ": synchronized in a()");
                for(int i = 0; i< 5; i++) {
                        System.out.println(Thread.currentThread().getName() + ": synchronized in a() for -> " + i);
                        try {
                                TimeUnit.SECONDS.sleep(1);
                        } catch (Exception e) {
                                e.printStackTrace();
                        }
                }
        }
        
        /**
         * synchronized 关键字修饰在类的普通方法中,此时线程调用该方法,
         * 需要获取的锁对象是类实例对象锁,相当于this
         */
        synchronized public void b() {
                System.out.println(Thread.currentThread().getName() + ": synchronized in b()");
                for(int i = 0; i< 5; i++) {
                        System.out.println(Thread.currentThread().getName() + ": synchronized in b() for -> " + i);
                        try {
                                TimeUnit.SECONDS.sleep(1);
                        } catch (Exception e) {
                                e.printStackTrace();
                        }
                }
        }
        
        /**
         * 该方法和a()方法竞争同一把锁
         */
        public void c() {
                System.out.println(Thread.currentThread().getName() + ": not synchronized in c()");
                synchronized (Foo.class) {
                        for(int i = 0; i< 5; i++) {
                                System.out.println(Thread.currentThread().getName() + ": synchronized in c() for -> " + i);
                                try {
                                        TimeUnit.SECONDS.sleep(1);
                                } catch (Exception e) {
                                        e.printStackTrace();
                                }
                        }
                }
        }
        
        /**
         * 该方法和b()方法竞争同一把锁
         */
        public void d() {
                System.out.println(Thread.currentThread().getName() + ": not synchronized in d()");
                synchronized (this) {
                        for(int i = 0; i< 5; i++) {
                                System.out.println(Thread.currentThread().getName() + ": synchronized in d() for -> " + i);
                                try {
                                        TimeUnit.SECONDS.sleep(1);
                                } catch (Exception e) {
                                        e.printStackTrace();
                                }
                        }
                }
        }
        
        public static void doRun() {
                Foo s = new Foo();
                
                // 创建一个线程执行a()
                new Thread() {
                        public void run() {
                                Foo.a();
                        }
                }.start();
                
                // 创建一个线程执行b()
                new Thread() {
                        public void run() {
                                s.b();
                        }
                }.start();
                
                // 创建一个线程执行b()
                new Thread() {
                        public void run() {
                                s.c();
                        }
                }.start();
                
                // 使用主线程执行c()
                s.d();
                
                System.out.println("main thread over");
        }
        
}

详细案例参考如下代码示例:

package org.xyz.java.basic.keys;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
 * synchronized 关键字讲解
 * @author kevin.chen
 */
public class SynchronizedDemo2 {
        
        public static void main(String[] args) {
                /**
                 * 线程竞争同一把锁,竞争到锁的线程进行操作,没有竞争到锁的线程阻塞
                 	   Thread-0: not synchronized in a()
                        Thread-1: not synchronized in b()
                        main: not synchronized in c()
                        Thread-0: synchronized in a() for -> 0
                        Thread-0: synchronized in a() for -> 1
                        Thread-0: synchronized in a() for -> 2
                        Thread-0: synchronized in a() for -> 3
                        Thread-0: synchronized in a() for -> 4
                        main: synchronized in c() for -> 0
                        main: synchronized in c() for -> 1
                        main: synchronized in c() for -> 2
                        main: synchronized in c() for -> 3
                        main: synchronized in c() for -> 4
                        Thread-1: synchronized in b() for -> 0
                        Thread-1: synchronized in b() for -> 1
                        Thread-1: synchronized in b() for -> 2
                        Thread-1: synchronized in b() for -> 3
                        Thread-1: synchronized in b() for -> 4
                 */
                //		Sd01.doRun();
                
                /**
                 * 线程竞争各自的锁,线程之间不存在竞争关系,无阻塞
                 	   Thread-0: not synchronized in a()
                        main: not synchronized in c()
                        main: synchronized in c() for -> 0
                        Thread-0: synchronized in a() for -> 0
                        Thread-1: not synchronized in b()
                        Thread-1: synchronized in b() for -> 0
                        Thread-0: synchronized in a() for -> 1
                        Thread-1: synchronized in b() for -> 1
                        main: synchronized in c() for -> 1
                        Thread-0: synchronized in a() for -> 2
                        main: synchronized in c() for -> 2
                        Thread-1: synchronized in b() for -> 2
                        main: synchronized in c() for -> 3
                        Thread-0: synchronized in a() for -> 3
                        Thread-1: synchronized in b() for -> 3
                        main: synchronized in c() for -> 4
                        Thread-0: synchronized in a() for -> 4
                        Thread-1: synchronized in b() for -> 4
                        main thread over
                 */
                //		Sd02.doRun();
                
                /**
                 * 线程竞争同一把锁,竞争到锁的线程进行操作,没有竞争到锁的线程阻塞(效果和Sd01一致,但比使用synchronized比较灵活)
                 	   Thread-0: not synchronized in a()
                        main: not synchronized in c()
                        Thread-0: synchronized in a() for -> 0
                        Thread-1: not synchronized in b()
                        Thread-0: synchronized in a() for -> 1
                        Thread-0: synchronized in a() for -> 2
                        Thread-0: synchronized in a() for -> 3
                        Thread-0: synchronized in a() for -> 4
                        main: synchronized in c() for -> 0
                        main: synchronized in c() for -> 1
                        main: synchronized in c() for -> 2
                        main: synchronized in c() for -> 3
                        main: synchronized in c() for -> 4
                        Thread-1: synchronized in b() for -> 0
                        main thread over
                        Thread-1: synchronized in b() for -> 1
                        Thread-1: synchronized in b() for -> 2
                        Thread-1: synchronized in b() for -> 3
                        Thread-1: synchronized in b() for -> 4
                 */
                //		Sd03.doRun();
                /**
                 * 线程竞争各自的锁,线程之间不存在竞争关系,
                 * 无阻塞(效果和Sd02一致,但比使用synchronized比较灵活)
                        Thread-0: not synchronized in a()
                        Thread-0: synchronized in a() for -> 0
                        main: not synchronized in c()
                        main: synchronized in c() for -> 0
                        Thread-1: not synchronized in b()
                        Thread-1: synchronized in b() for -> 0
                        main: synchronized in c() for -> 1
                        Thread-0: synchronized in a() for -> 1
                        Thread-1: synchronized in b() for -> 1
                        main: synchronized in c() for -> 2
                        Thread-0: synchronized in a() for -> 2
                        Thread-1: synchronized in b() for -> 2
                        main: synchronized in c() for -> 3
                        Thread-0: synchronized in a() for -> 3
                        Thread-1: synchronized in b() for -> 3
                        main: synchronized in c() for -> 4
                        Thread-1: synchronized in b() for -> 4
                        Thread-0: synchronized in a() for -> 4
                        main thread over
                 */
                Sd04.doRun();
        }
}
/**
 * 同步代码块中使用的都是this对象(任意同一对象都类似)作为对象锁,
 * 所以这3个方法竞争的是同一把锁,当3个线程(含主线程)中的任意一个线程拿到锁后,其他线程都进入阻塞排队状态
 * @author kevin.chen
 */
class Sd01 {
        
        public void a() {
                System.out.println(Thread.currentThread().getName() + ": not synchronized in a()");
                /*
                 * 这里使用this,也可以这样
                 * 	Object obj = new Object();
                 * 	synchronized (obj)
                 */
                synchronized (this) {
                        for(int i = 0; i< 5; i++) {
                                System.out.println(Thread.currentThread().getName() + ": synchronized in a() for -> " + i);
                                try {
                                        TimeUnit.SECONDS.sleep(1);
                                } catch (Exception e) {
                                        e.printStackTrace();
                                }
                        }
                }
        }
        
        public void b() {
                System.out.println(Thread.currentThread().getName() + ": not synchronized in b()");
                /*
                 * 这里使用this,也可以这样
                 * 	Object obj = new Object();
                 * 	synchronized (obj)
                 */
                synchronized (this) {
                        for(int i = 0; i< 5; i++) {
                                System.out.println(Thread.currentThread().getName() + ": synchronized in b() for -> " + i);
                                try {
                                        TimeUnit.SECONDS.sleep(1);
                                } catch (Exception e) {
                                        e.printStackTrace();
                                }
                        }
                }
        }
        
        public void c() {
                System.out.println(Thread.currentThread().getName() + ": not synchronized in c()");
                /*
                 * 这里使用this,也可以这样
                 * 	Object obj = new Object();
                 * 	synchronized (obj)
                 */
                synchronized (this) {
                        for(int i = 0; i< 5; i++) {
                                System.out.println(Thread.currentThread().getName() + ": synchronized in c() for -> " + i);
                                try {
                                        TimeUnit.SECONDS.sleep(1);
                                } catch (Exception e) {
                                        e.printStackTrace();
                                }
                        }
                }
        }
        
        public static void doRun() {
                Sd01 s = new Sd01();
                
                // 创建一个线程执行a()
                new Thread() {
                        public void run() {
                                s.a();
                        }
                }.start();
                // 创建一个线程执行b()
                new Thread() {
                        public void run() {
                                s.b();
                        }
                }.start();
                
                // 使用主线程执行c()
                s.c();
                
                System.out.println("main thread over");
        }
        
}
/**
 * 每个方法使用不同的锁,多个线程调用不同的方法,竞争的是不同的锁,
 * 因此调用不同的方法,线程直接不会有锁竞争存在
 * @author kevin.chen
 */
class Sd02 {
        
        final byte[] bt = new byte[0];        // 这个比用对象要节约空间,只需执行3行代码完成创建
        final Object obj = new Object();      // 需要执行7行代码完成创建
        
        public void a() {
                System.out.println(Thread.currentThread().getName() + ": not synchronized in a()");
                // 这里使用this对象作为同步锁
                synchronized (this) {
                        for(int i = 0; i< 5; i++) {
                                System.out.println(Thread.currentThread().getName() + ": synchronized in a() for -> " + i);
                                try {
                                        TimeUnit.SECONDS.sleep(1);
                                } catch (Exception e) {
                                        e.printStackTrace();
                                }
                        }
                }
        }
        
        public void b() {
                System.out.println(Thread.currentThread().getName() + ": not synchronized in b()");
                // 这里使用bt对象作为同步锁
                synchronized (bt) {
                        for(int i = 0; i< 5; i++) {
                                System.out.println(Thread.currentThread().getName() + ": synchronized in b() for -> " + i);
                                try {
                                        TimeUnit.SECONDS.sleep(1);
                                } catch (Exception e) {
                                        e.printStackTrace();
                                }
                        }
                }
        }
        
        public void c() {
                System.out.println(Thread.currentThread().getName() + ": not synchronized in c()");
                // 这里使用obj对象作为同步锁
                synchronized (obj) {
                        for(int i = 0; i< 5; i++) {
                                System.out.println(Thread.currentThread().getName() + ": synchronized in c() for -> " + i);
                                try {
                                        TimeUnit.SECONDS.sleep(1);
                                } catch (Exception e) {
                                        e.printStackTrace();
                                }
                        }
                }
        }
        
        public static void doRun() {
                Sd02 s = new Sd02();
                
                // 创建一个线程执行a()
                new Thread() {
                        public void run() {
                                s.a();
                        }
                }.start();
                // 创建一个线程执行b()
                new Thread() {
                        public void run() {
                                s.b();
                        }
                }.start();
                
                // 使用主线程执行c()
                s.c();
                
                System.out.println("main thread over");
        }
        
}
/**
 * 使用Lock来代替synchronized关键字来实现同步操作,
 * 所有的线程竞争同一把锁,没有竞争到锁的线程是阻塞的
 * @author kevin.chen
 */
class Sd03 {
        
        private Lock lock = new ReentrantLock();
        
        public void a() {
                System.out.println(Thread.currentThread().getName() + ": not synchronized in a()");
                // 加锁
                lock.lock();
                try {
                        for(int i = 0; i< 5; i++) {
                                System.out.println(Thread.currentThread().getName() + ": synchronized in a() for -> " + i);
                                try {
                                        TimeUnit.SECONDS.sleep(1);
                                } catch (Exception e) {
                                        e.printStackTrace();
                                }
                        }
                } finally {
                        // 释放锁
                        lock.unlock();
                }
        }
        
        public void b() {
                System.out.println(Thread.currentThread().getName() + ": not synchronized in b()");
                // 加锁
                lock.lock();
                try{
                        for(int i = 0; i< 5; i++) {
                                System.out.println(Thread.currentThread().getName() + ": synchronized in b() for -> " + i);
                                try {
                                        TimeUnit.SECONDS.sleep(1);
                                } catch (Exception e) {
                                        e.printStackTrace();
                                }
                        }
                } finally {
                        // 释放锁
                        lock.unlock();
                }
        }
        
        public void c() {
                System.out.println(Thread.currentThread().getName() + ": not synchronized in c()");
                // 加锁
                lock.lock();
                try {
                        for(int i = 0; i< 5; i++) {
                                System.out.println(Thread.currentThread().getName() + ": synchronized in c() for -> " + i);
                                try {
                                        TimeUnit.SECONDS.sleep(1);
                                } catch (Exception e) {
                                        e.printStackTrace();
                                }
                        }
                } finally {
                        // 释放锁
                        lock.unlock();
                }
        }
        
        public static void doRun() {
                Sd03 s = new Sd03();
                
                // 创建一个线程执行a()
                new Thread() {
                        public void run() {
                                s.a();
                        }
                }.start();
                // 创建一个线程执行b()
                new Thread() {
                        public void run() {
                                s.b();
                        }
                }.start();
                
                // 使用主线程执行c()
                s.c();
                
                System.out.println("main thread over");
        }
        
}
/**
 * 使用Lock来代替synchronized关键字来实现同步操作,
 * 每个方法使用不同的锁,多个线程调用不同的方法,竞争的是不同的锁,
 * 因此调用不同的方法,线程直接不会有锁竞争存在
 * @author kevin.chen
 */
class Sd04 {
        
        private Lock lockA = new ReentrantLock();
        private Lock lockB = new ReentrantLock();
        private Lock lockC = new ReentrantLock();
        
        public void a() {
                System.out.println(Thread.currentThread().getName() + ": not synchronized in a()");
                // 加锁
                lockA.lock();
                try {
                        for(int i = 0; i< 5; i++) {
                                System.out.println(Thread.currentThread().getName() + ": synchronized in a() for -> " + i);
                                try {
                                        TimeUnit.SECONDS.sleep(1);
                                } catch (Exception e) {
                                        e.printStackTrace();
                                }
                        }
                } finally {
                        // 释放锁
                        lockA.unlock();
                }
        }
        
        public void b() {
                System.out.println(Thread.currentThread().getName() + ": not synchronized in b()");
                // 加锁
                lockB.lock();
                try{
                        for(int i = 0; i< 5; i++) {
                                System.out.println(Thread.currentThread().getName() + ": synchronized in b() for -> " + i);
                                try {
                                        TimeUnit.SECONDS.sleep(1);
                                } catch (Exception e) {
                                        e.printStackTrace();
                                }
                        }
                } finally {
                        // 释放锁
                        lockB.unlock();
                }
        }
        
        public void c() {
                System.out.println(Thread.currentThread().getName() + ": not synchronized in c()");
                // 加锁
                lockC.lock();
                try {
                        for(int i = 0; i< 5; i++) {
                                System.out.println(Thread.currentThread().getName() + ": synchronized in c() for -> " + i);
                                try {
                                        TimeUnit.SECONDS.sleep(1);
                                } catch (Exception e) {
                                        e.printStackTrace();
                                }
                        }
                } finally {
                        // 释放锁
                        lockC.unlock();
                }
        }
        
        public static void doRun() {
                Sd04 s = new Sd04();
                
                // 创建一个线程执行a()
                new Thread() {
                        public void run() {
                                s.a();
                        }
                }.start();
                // 创建一个线程执行b()
                new Thread() {
                        public void run() {
                                s.b();
                        }
                }.start();
                
                // 使用主线程执行c()
                s.c();
                
                System.out.println("main thread over");
        }
        
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值