`
ivan
  • 浏览: 179564 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

java synchronized 同步机制解析

    博客分类:
  • java
阅读更多
在Java 5以前,是用synchronized关键字来实现锁的功能。

synchronized关键字可以作为方法的修饰符(同步方法),也可作用于函数内的语句(同步代码块)。

掌握synchronized,关键是要掌握把那个东西作为锁。对于类的非静态方法(成员方法)而言,意味着要取得对象实例的锁;对于类的静态方法(类方法)而言,要取得类的Class对象的锁;对于同步代码块,要指定取得的是哪个对象的锁。同步非静态方法可以视为包含整个方法的synchronized(this) { … }代码块。   

不管是同步代码块还是同步方法,每次只有一个线程可以进入(在同一时刻最多只有一个线程执行该段代码。),如果其他线程试图进入(不管是同一同步块还是不同的同步块),jvm会将它们挂起(放入到等锁池中)。这种结构在并发理论中称为临界区(critical section)。

在jvm内部,为了提高效率,同时运行的每个线程都会有它正在处理的数据的缓存副本,当我们使用synchronzied进行同步的时候,真正被同步的是在不同线程中表示被锁定对象的内存块(副本数据会保持和主内存的同步,现在知道为什么要用同步这个词汇了吧),简单的说就是在同步块或同步方法执行完后,对被锁定的对象做的任何修改要在释放锁之前写回到主内存中;在进入同步块得到锁之后,被锁定对象的数据是从主内存中读出来的,持有锁的线程的数据副本一定和主内存中的数据视图是同步的 。 

下面举具体的例子来说明synchronized的各种情况。

## 两个线程同时访问一个对象的同步方法
当两个并发线程访问同一个对象的同步方法时,只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个以后才能执行。
public class TwoThread {
    public static void main(String[] args) {
        final TwoThread twoThread = new TwoThread();

        Thread t1 = new Thread(new Runnable() {
            public void run() {
                twoThread.syncMethod();
            }
        }, "A");
        Thread t2 = new Thread(new Runnable() {
            public void run() {
                twoThread.syncMethod();
            }
        }, "B");

        t1.start();
        t2.start();
    }

    public synchronized void syncMethod() {
        for (int i = 0; i < 5; i++) {
            System.out.println(Thread.currentThread().getName() + " : " + i);
            try {
                Thread.sleep(500);
            } catch (InterruptedException ie) {
            }
        }
    }

}


输出结果:
A : 0
A : 1
A : 2
A : 3
A : 4
B : 0
B : 1
B : 2
B : 3
B : 4

## 两个线程访问的是两个对象的同步方法
这种情况下,synchronized不起作用,跟普通的方法一样。因为对应的锁是各自的对象。
public class TwoObject {
    public static void main(String[] args) {
        final TwoObject object1 = new TwoObject();
        Thread t1 = new Thread(new Runnable() {
            public void run() {
                object1.syncMethod();
            }
        }, "Object1");
        t1.start();

        final TwoObject object2 = new TwoObject();
        Thread t2 = new Thread(new Runnable() {
            public void run() {
                object2.syncMethod();
            }
        }, "Object2");
        t2.start();
    }

    public synchronized void syncMethod() {
        for (int i = 0; i < 5; i++) {
            System.out.println(Thread.currentThread().getName() + " : " + i);
            try {
                Thread.sleep(500);
            } catch (InterruptedException ie) {
            }
        }
    }

}

其中一种可能的输出结果:
Object2 : 0
Object1 : 0
Object1 : 1
Object2 : 1
Object2 : 2
Object1 : 2
Object2 : 3
Object1 : 3
Object1 : 4
Object2 : 4

## 两个线程访问的是synchronized的静态方法
这种情况,由于锁住的是Class,在任何时候,该静态方法只有一个线程可以执行。

## 同时访问同步方法与非同步方法
当一个线程访问对象的一个同步方法时,另一个线程仍然可以访问该对象中的非同步方法。
public class SyncAndNoSync {
    public static void main(String[] args) {
        final SyncAndNoSync syncAndNoSync = new SyncAndNoSync();

        Thread t1 = new Thread(new Runnable() {
            public void run() {
                syncAndNoSync.syncMethod();
            }
        }, "A");
        t1.start();

        Thread t2 = new Thread(new Runnable() {
            public void run() {
                syncAndNoSync.noSyncMethod();
            }
        }, "B");
        t2.start();
    }

    public synchronized void syncMethod() {
        for (int i = 0; i < 5; i++) {
            System.out.println(Thread.currentThread().getName() + " at syncMethod(): " + i);
            try {
                Thread.sleep(500);
            } catch (InterruptedException ie) {
            }
        }
    }

    public void noSyncMethod() {
        for (int i = 0; i < 5; i++) {
            System.out.println(Thread.currentThread().getName() + " at noSyncMethod(): " + i);
            try {
                Thread.sleep(500);
            } catch (InterruptedException ie) {
            }
        }
    }

}

一种可能的输出结果:
B at noSyncMethod(): 0
A at syncMethod(): 0
B at noSyncMethod(): 1
A at syncMethod(): 1
B at noSyncMethod(): 2
A at syncMethod(): 2
B at noSyncMethod(): 3
A at syncMethod(): 3
A at syncMethod(): 4
B at noSyncMethod(): 4

## 访问同一个对象的不同同步方法
当一个线程访问一个对象的同步方法A时,其他线程对该对象中所有其它同步方法的访问将被阻塞。因为第一个线程已经获得了对象锁,其他线程得不到锁,则虽然是访问不同的方法,但是没有获得锁,也无法访问。
public class TwoSyncMethod {
    public static void main(String[] args) {
        final TwoSyncMethod twoSyncMethod = new TwoSyncMethod();

        Thread t1 = new Thread(new Runnable() {
            public void run() {
                twoSyncMethod.syncMethod1();
            }
        }, "A");
        t1.start();

        Thread t2 = new Thread(new Runnable() {
            public void run() {
                twoSyncMethod.syncMethod2();
            }
        }, "B");
        t2.start();
    }

    public synchronized void syncMethod1() {
        for (int i = 0; i < 5; i++) {
            System.out.println(Thread.currentThread().getName() + " at syncMethod1(): " + i);
            try {
                Thread.sleep(500);
            } catch (InterruptedException ie) {
            }
        }
    }

    public synchronized void syncMethod2() {
        for (int i = 0; i < 5; i++) {
            System.out.println(Thread.currentThread().getName() + " at syncMethod2(): " + i);
            try {
                Thread.sleep(500);
            } catch (InterruptedException ie) {
            }
        }
    }

}

输出结果:
A at syncMethod1(): 0
A at syncMethod1(): 1
A at syncMethod1(): 2
A at syncMethod1(): 3
A at syncMethod1(): 4
B at syncMethod2(): 0
B at syncMethod2(): 1
B at syncMethod2(): 2
B at syncMethod2(): 3
B at syncMethod2(): 4
分享到:
评论

相关推荐

    synchronized用法大全实例

    java多线程编程核心技术synchronized实例大全,同步方法,同步语句块,类锁,对象锁全都用代码来展现出来

    Java多线程同步Synchronized深入解析

    同步的概念:  同步分为同步方法和同步块两种...  无论你将Synchronized加在方法前还是加在一个变量前,其锁定的都是一个 类对象。每一个对象都只有一个锁与之相关联。  下例中分情况的列举各种情况下的同步效果

    详细解读java同步之synchronized解析

    synchronized关键字是Java里面最基本的同步手段,下面我们来一起学习一下

    java线程深入解析

    java线程深入讲解,可以了解java线程同步语安全,实现的方法和synchronized锁的使用与安全控制等等,谁用谁知道好用

    Java 多线程同步 锁机制与synchronized深入解析

    从尺寸上讲,同步代码块比同步方法小。你可以把同步代码块看成是没上锁房间里的一块用带锁的屏风隔开的空间

    实例解析Java中的synchronized关键字与线程安全问题

    synchronized代码块,被修饰的代码成为同步语句块,其作用的范围是调用这个代码块的对象,我们在用synchronized关键字的时候,能缩小代码段的范围就尽量缩小,能在代码段上加同步就不要再整个方法上加同步。...

    Java并发编程原理与实战

    通过生产者消费者模型理解等待唤醒机制.mp4 Condition的使用及原理解析.mp4 使用Condition重写waitnotify案例并实现一个有界队列.mp4 深入解析Condition源码.mp4 实战:简易数据连接池.mp4 线程之间通信之join应用与...

    Java 多线程编程面试集锦20道问题解答Java多线程编程高难度面试题及解析

    本篇文章提供了20道高难度的Java多线程编程面试题及详细解析,旨在帮助开发者展示出卓越的并发编程能力。在当今高并发的应用场景下,对多线程编程的理解和应用是评估面试者的重要指标。通过这些高难度问题,您将全面...

    JAVA实现Modbus RTU或Modbus TCPIP数据采集.rar

    3.java同步的几种方式:synchronized,volatile,显示锁,原子变量,线程及对象的基础同步方法。 4.所谓线程安全就是当多个线程访问某个类时,不管运行时环境采用何种调度方式或者这些线程将如何交替执行,并且在...

    深入解析Java并发程序中线程的同步与线程锁的使用

    主要介绍了深入解析Java并发编程中线程的同步与线程锁的使用,synchronized和lock是Java中最常见的控制线程的方法,需要的朋友可以参考下

    javaconcurrent源码-java7-source-code:Java7源码/Concurrency同步

    Synchronized 同步容器 Concurrent 并发容器: Map/List/Queue 阻塞队列 JUC锁: CountDownLatch 闭锁 AQS 锁的公共类 20180514 String, 部分Character 20180508 除 Set 外, 常用的 Collection 都已经分析完毕 简化...

    基于JDK源码解析Java领域中的并发锁之设计与实现.pdf

    虽然,Java在基于语法层面(synchronized 关键字)实现了对管程技术,但是从使用方式和性能上来说,内置锁(synchronized 关键字)的粒度相对过大,不支持超时和中断等问题。 为了弥补这些问题,从JDK层面对其“重复造...

    java基础案例与开发详解案例源码全

    12.5.1 使用synchronized同步块324 12.5.2 使用集合工具类同步化集合类对象324 12.5.3 使用JDK5.0后提供的并发集合类324 12.6 用Timer类调度任务325 12.7 本章练习326 第13章 13.1 java.io.File类328 13.1.1 文件和...

    Java多线程

    详细介绍了Java的多线程之间的同步,对Synchronized和Lock进去深入解析,希望能帮到大家

    java 面试题 总结

    assertion(断言)在软件开发中是一种常用的调试方式,很多开发语言中都支持这种机制。在实现中,assertion就是在程序中的一条语句,它对一个boolean表达式进行检查,一个正确程序必须保证这个boolean表达式的值为...

    java面试题

    14. 简述synchronized和java.util.concurrent.locks.Lock的异同 ? 11 15. 当一个线程进入一个对象的一个synchronized方法后,其它线程是否可进入此对象的其它方法? 11 16. abstract class和interface有什么区别? 12...

    java面试宝典

    203、编程用JAVA解析XML的方式. 49 204、EJB2.0有哪些内容?分别用在什么场合? EJB2.0和EJB1.1的区别? 51 205、EJB与JAVA BEAN的区别? 51 206、EJB的基本架构 51 207、MVC的各个部分都有那些技术来实现?如何实现? 52...

    Java面试宝典-经典

    54、简述synchronized和java.util.concurrent.locks.Lock的异同 ? 34 55、设计4个线程,其中两个线程每次对j增加1,另外两个线程对j每次减少1。写出程序。 36 56、子线程循环10次,接着主线程循环100,接着又回到...

Global site tag (gtag.js) - Google Analytics