`

使用synchronized进行Java线程同步

    博客分类:
  • Java
阅读更多

在开始本文之前,建议阅读
范例解说Java里的线程概念与线程同步技术
一文,对Java的线程处理做一个全面了解。

线程同步指多个线程同时访问某资源时,采用一系列的机制以保证同时最多只能一个线程访问该资源。
为什么需要线程同步呢?
我们举一个最简单的例子来说明为什么需要线程同步。
比如有一本书(有且只有一本),交给多个售货员同时去卖;
如果其中任何一个售货员把这本书给卖了,其他售货员就不能再卖这本书了。
现实生活中,如果要保证该书不会被多个售货员同时卖掉,必须要有一种机制来保证:
比如,售货员应该拿到该书之后才能开始卖书,暂时拿不到的话就只能等该书被退回柜台。

售书的完整的例子可以参考 范例解说Java里的线程概念与线程同步技术 一文

这里,每一个售货员售书可以看作一个线程。欲售的书便是各线程需要共享的资源。
开始售书之前,需要取得该书(资源),取不到情况下等待:资源取得
开始售书之后,则需要取得对该书的独享控制(不让他人拿到该书):资源加锁
售完书时,需要通知柜台该书已售出;或者未售出时,把书退回柜台(通知他人可以拿到该书):资源解锁

synchronized控制线程同步的概念跟此完全一样。
Java里可以使用synchronized来同步代码块或者方法。
同步代码块例:

synchronized(欲同步的对象obj) {   
    需要同步的代码块   
}  

 

可以同步代码块。

synchronized (obj) 表示若多个线程同时访问时,只让其中一个线程最先取得obj对象并对其加锁,其它线程则阻塞直到取得obj对象的线程执行完代码块,此时被加锁的obj对象得到释放(解锁),其它线程得到通知取得该book对象继续执行。
很多情况下,可以使用synchronized (this){...}来同步代码块。但需要注意的是,使用this作为同步对象的话,如果同一个类中存在多个synchronized (this){...}代码块,其中任何一个synchronized(this)代码块处于被执行状态,则其它线程对其他synchronized(this)代码块的访问也会受到阻塞。
为了说明这个问题,我们举例说明:

public class HelloSynchronized {   
  
    public static void main(String[] args) {   
        //   
        HelloSynchronized helloSynchronized = new HelloSynchronized();   
        //创建2个线程t1, t2,分别调用HelloSynchronized helloSynchronized的2个方法method1,与method2   
        Thread t1 = new Thread(new HelloSynchronizedRunnalbe(helloSynchronized, "method1"), "t1");   
        Thread t2 = new Thread(new HelloSynchronizedRunnalbe(helloSynchronized, "method2"), "t2");   
           
        t1.start();   
        t2.start();   
  
    }   
  
    //synchronized public void method1() {    //同步方法   
    public void method1() {   
        synchronized (this) {    //同步块   
  
            System.out.println(Thread.currentThread().getName()   
                    + " enter method1");   
            try {   
                Thread.sleep(3000);   
            } catch (InterruptedException e) {   
                // do nothing   
            }   
            System.out.println(Thread.currentThread().getName()   
                    + " exit method1");   
        }   
    }   
  
    //synchronized public void method2() {    //同步方法   
    public void method2() {   
        synchronized (this) {    //同步块   
            System.out.println(Thread.currentThread().getName()   
                    + " enter method2");   
            try {   
                Thread.sleep(3000);   
            } catch (InterruptedException e) {   
                // do nothing   
            }   
            System.out.println(Thread.currentThread().getName()   
                    + " exit method2");   
        }   
    }   
}   
  
class HelloSynchronizedRunnalbe implements Runnable {   
    private HelloSynchronized helloSynchronized;   
    private String methodName;   
    public HelloSynchronizedRunnalbe(HelloSynchronized helloSynchronized, String methodName) {   
        this.helloSynchronized = helloSynchronized;   
        this.methodName = methodName;   
    }   
    public void run() {   
        if (methodName.equals("method1")) {   
            helloSynchronized.method1();   
        } else if (methodName.equals("method2")) {   
            helloSynchronized.method2();   
        }   
    }   
}  

 

运行结果为:

t1 enter method1
t1 exit method1
t2 enter method2
t2 exit method2

等到线程t1结束后,t2才开始运行(t2受到阻塞)

再把synchronized (this)去掉,运行结果为:

t1 enter method1
t2 enter method2
t1 exit method1
t2 exit method2

线程t1,t2同时运行

同步方法例:

view plaincopy to clipboardprint?
synchronized private void sellBook(Book book) {   
...   
}  

 

这种方法其实相当于

view plaincopy to clipboardprint?
private void sellBook(Book book) {   
    synchronized(this) {   
        ...   
    }   
} 

 

由于默认采用this作为同步对象,所以当一个类中有多个synchronized方法时,同样会存在以上问题:即如果有一个线程访问其中某个synchronized方法时,直到该方法执行完毕,其它线程对其它synchronized方法的访问也将受到阻塞。
大家可以把上面的例子稍加改造,去掉代码中的synchronized (this),改为synchronized public void method1(),synchronized public void method2()同步形式,运行后会得到同样结果。

多同步代码块synchronized(this){...}的多线程阻塞问题(包括synchronized同步方法),在并发处理的系统中(比如WEB服务器)会严重影响性能,建议慎重使用。可以使用synchronized(obj){...}缩小同步资源对象的范围来解决这个问题。

分享到:
评论

相关推荐

    使用synchronized实现多线程同步.pdf

    在Java编程中,多线程同步是一个至关重要的概念,它确保了多个线程在访问共享资源时能够有序进行,防止数据不一致性和竞态条件。`synchronized`关键字是Java中实现线程同步的主要手段之一。这篇文档主要讨论了如何...

    Java多线程同步.pdf

    Java多线程同步是指在Java语言中,如何使用synchronized关键字和其他同步机制来确保多线程程序的正确执行。在Java语言中,synchronized关键字用于对方法或者代码块进行同步,但是仅仅使用synchronized关键字还不能...

    java的线程同步机制synchronized关键字的理解_.docx

    Java 线程同步机制中 synchronized 关键字的理解 Java 的线程同步机制是为了解决多个线程共享同一片存储空间所带来的访问冲突问题。其中,synchronized 关键字是 Java 语言中解决这种冲突的重要机制。 ...

    使用synchronized实现多线程同步[借鉴].pdf

    总之,`synchronized`关键字是Java中实现线程同步的关键手段,它可以确保共享数据在多线程环境中的正确性,但也需要谨慎使用,以避免可能导致的问题。在实际开发中,根据具体需求选择合适的方法来实现同步是至关重要...

    java 线程同步 信号量控制同步

    Java 中的 synchronized 关键字可以用于实现线程同步。synchronized 关键字可以用来锁定对象或方法,防止多个线程同时访问同一个共享资源。 在 Java 中,还有其他线程同步机制,如volatile 变量、Atomic 变量、Lock...

    基于Java synchronized同步锁实现线程交互.pdf

    "基于Java synchronized同步锁实现线程交互" Java多线程能够提高CPU利用...因此,在使用Java多线程的场景中,请充分理解Java线程各状态之间的关系及其切换,并使用synchronized、wait()和notify()方法实现线程交互。

    java Thread & synchronized & concurrent 线程、同步、并发

    Java提供了`synchronized`关键字来实现线程同步。当一个方法或代码块被`synchronized`修饰时,同一时刻只能有一个线程访问该区域。这样可以保证在多线程环境下的数据一致性。 并发是指多个任务在一段时间内交替执行...

    java线程同步详解

    总结一下,Java线程同步的关键点: 1. **线程同步是为了解决共享资源的并发访问问题,防止数据不一致和冲突。** 2. **同步意味着线程排队,依次访问共享资源,而不是同时访问。** 3. **只有共享变量(可变状态)才...

    java线程同步及通信

    Java线程同步与通信是多线程编程中的关键概念,用于解决并发访问共享资源时可能出现的数据不一致性和竞态条件问题。以下将详细介绍这两个主题,以及如何通过代码示例进行演示。 1. **线程同步**: 线程同步是确保...

    Java 线程同步调用

    在深入探讨Java线程同步调用这一主题之前,我们首先需要理解线程同步的基本概念及其在多线程环境中的重要性。线程同步是多线程编程中的一个关键概念,它确保了多个线程在访问共享资源时不会发生冲突,避免了数据不...

    Java线程及同步(synchronized)样例代码

    ### Java线程及同步(synchronized)样例代码解析 #### 一、概述 本篇文章主要分析一个关于Java线程及其同步机制(synchronized)的示例代码。该示例展示了如何在多线程环境中使用`synchronized`关键字来实现线程...

    Java多线程同步机制研究分析.pdf

    Java多线程同步机制有两种类型:synchronized方法和synchronized块。synchronized方法是将访问共享资源的方法标记为synchronized,然后该标记的方法来控制对类成员变量的访问。synchronized块是将程序的某段代码使用...

    操作系统实验 多线程同步与互斥 java编写 有界面

    在“操作系统实验 多线程同步与互斥 java编写 有界面”的实验中,可能需要设计一个图形用户界面(GUI),通过按钮或事件触发线程的创建和同步操作,直观地展示线程间的交互和同步效果。例如,可以模拟银行账户转账,...

    java同步synchronized关键字用法示例

    Java中的`synchronized`关键字是多线程编程中的一个重要概念,用于控制并发访问共享资源时的同步机制。在Java中,当多个线程试图同时访问和修改同一块代码或数据时,可能会导致数据不一致的问题。为了解决这个问题,...

    Java多线程同步具体实例.doc

    这个实例展示了如何在Java中使用多线程同步来避免竞态条件,确保数据的一致性。在实际开发中,我们应当根据具体情况选择适合的同步策略,如使用同步方法、同步块,或者其他的并发控制工具,如`ReentrantLock`等,以...

    Java线程同步例子.pdf

    在Java中,线程同步是保证多线程安全...上述Java线程同步例子中涉及到的代码虽然是片段,但涵盖了线程同步处理的多个重要方面,帮助我们理解和使用Java线程同步机制,以及在设计和实现多线程应用程序时的实践和技巧。

    Java多线程和同步

    Java线程(二):线程同步synchronized和volatile 详细讲解Java 同步的原理技术资料

Global site tag (gtag.js) - Google Analytics