`

java中synchronized用法

    博客分类:
  • java
阅读更多

package nlc.tools.common;

public class TextThread {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		TxtThread tt = new TxtThread();
		new Thread(tt).start();
		new Thread(tt).start();
		new Thread(tt).start();
		new Thread(tt).start();
	}
}

class TxtThread implements Runnable {
	int num = 100;
	String str = new String();
	public void run() {
		while (true) {
			synchronized (str) {
				if (num > 0) {
					try {
						Thread.sleep(10);
					} catch (Exception e) {
						e.getMessage();
					}
					System.out.println(Thread.currentThread().getName()
							+ " this is " + num--);
				}
			}
		}
	}
}

 

上面的例子中为了制造一个时间差,也就是出错的机会,使用了Thread.sleep(10)。

 

Java对多线程的支持与同步机制深受大家的喜爱,似乎看起来使用了synchronized关键字就可以轻松地解决多线程共享数据同步问题。到底如何?――还得对synchronized关键字的作用进行深入了解才可定论。

总的说来,synchronized关键字可以作为函数的修饰符,也可作为函数内的语句,也就是平时说的同步方法和同步语句块。如果再细的分类,synchronized可作用于instance变量、object reference(对象引用)、static函数和class literals(类名称字面常量)身上。

在进一步阐述之前,我们需要明确几点:

A.无论synchronized关键字加在方法上还是对象上,它取得的锁都是对象,而不是把一段代码或函数当作锁――而且同步方法很可能还会被其他线程的对象访问。

B.每个对象只有一个锁(lock)与之相关联。

C.实现同步是要很大的系统开销作为代价的,甚至可能造成死锁,所以尽量避免无谓的同步控制。

接着来讨论synchronized用到不同地方对代码产生的影响:

假设P1P2是同一个类的不同对象,这个类中定义了以下几种情况的同步块或同步方法,P1P2就都可以调用它们。

 

1.synchronized当作函数修饰符时,示例代码如下:

 

Public synchronized void methodAAA() {
    //….
}

 

这也就是同步方法,那这时synchronized锁定的是哪个对象呢?它锁定的是调用这个同步方法对象。也就是说,当一个对象P1在不同的线程中执行这个同步方法时,它们之间会形成互斥,达到同步的效果。但是这个对象所属的Class所产生的另一对象P2却可以任意调用这个被加了synchronized关键字的方法。

上边的示例代码等同于如下代码:

 

public void methodAAA() {
    synchronized (this) {//(1)
        //…..
    }
}

 

(1)处的this指的是什么呢?它指的就是调用这个方法的对象,如P1。可见同步方法实质是将synchronized作用于object reference。――那个拿到了P1对象锁的线程,才可以调用P1的同步方法,而对P2而言,P1这个锁与它毫不相干,程序也可能在这种情形下摆脱同步机制的控制,造成数据混乱:(

2.同步块,示例代码如下:

 

public void method3(SomeObject so) {
    synchronized(so) {
        //…..
    }
}

 

这时,锁就是so这个对象,谁拿到这个锁谁就可以运行它所控制的那段代码。当有一个明确的对象作为锁时,就可以这样写程序,但当没有明确的对象作为锁,只是想让一段代码同步时,可以创建一个特殊的instance变量(它得是一个对象)来充当锁:

 

class Foo implements Runnable {
    private byte[] lock = new byte[0];// 特殊的instance变量
   Public void methodA() {
        synchronized(lock) { //… }
    }
    //…..
}

 

注:零长度的byte数组对象创建起来将比任何对象都经济――查看编译后的字节码:生成零长度的byte[]对象只需3条操作码,而Object lock = new Object()则需要7行操作码。

3.将synchronized作用于static 函数,示例代码如下:

 

Class Foo {
    public synchronized static void methodAAA() {// 同步的static 函数
        //….
    }

    public void methodBBB() {
        synchronized(Foo.class);//class literal(类名称字面常量)
    }
}

 

代码中的methodBBB()方法是把class literal作为锁的情况,它和同步的static函数产生的效果是一样的,取得的锁很特别,是当前调用这个方法的对象所属的类(Class,而不再是由这个Class产生的某个具体对象了)。

记得在《Effective Java》一书中看到过将 Foo.class P1.getClass()用于作同步锁还不一样,不能用P1.getClass()来达到锁这个Class的目的。P1指的是由Foo类产生的对象。

可以推断:如果一个类中定义了一个synchronizedstatic函数A,也定义了一个synchronized instance函数B,那么这个类的同一对象Obj在多线程中分别访问AB两个方法时,不会构成同步,因为它们的锁都不一样。A方法的锁是Obj所属的那个Class,B的锁是Obj这个对象

 

小结如下:

搞清楚synchronized锁定的是哪个对象,就能帮助我们设计更安全的多线程程序。

 

 

还有一些技巧可以让我们对共享资源的同步访问更加安全:

1.定义private instance变量+它的 get方法,而不要定义public/protectedinstance变量。如果将变量定义为public,对象在外界可以绕过同步方法的控制而直接取得它,并改动它。这也是JavaBean的标准实现方式之一。

2.如果instance变量是一个对象,如数组或ArrayList什么的,那上述方法仍然不安全,因为当外界对象通过get方法拿到这个instance对象的引用后,又将其指向另一个对象,那么这个private变量也就变了,岂不是很危险。这个时候就需要将get方法也加上synchronized同步,并且,只返回这个private对象的clone()――这样,调用端得到的就是对象副本的引用了。

分享到:
评论

相关推荐

    java里面synchronized用法.doc

    Java 中的 synchronized 用法详解 Java 中的 synchronized 关键字是用于解决多线程并发问题的重要工具之一。它可以被用于方法、代码块和变量上,以实现对共享资源的互斥访问控制。本文将对 Java 中的 synchronized ...

    java同步synchronized关键字用法示例

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

    Java synchronized使用案例

    在`Synchronized`压缩包中,可能包含了通过实验来演示`synchronized`关键字使用的一些Java代码。例如,创建一个共享资源类,然后通过多个线程去操作这个资源,使用`synchronized`关键字来保证线程安全。实验可能涉及...

    java锁机制Synchronizedjava锁机制Synchronized

    Java 锁机制 Synchronized 是 Java 语言中的一种同步机制,用于解决多线程并发访问共享资源时可能出现的一些问题。 Java 锁机制 Synchronized 的概念 在 Java 中,每个对象都可以被看作是一个大房子,其中有多个...

    Java中synchronized正确使用方法解析

    Java 中 synchronized 正确使用方法解析 Java 中 synchronized 关键字是解决线程安全问题的重要手段,它可以确保在多线程环境下,共享资源的访问安全性。本文将详细介绍 Java 中 synchronized 的正确使用方法,通过...

    Java 中 synchronized的用法详解(四种用法)

    Java 中的 `synchronized` 关键字是多线程编程中的重要概念,用于实现线程同步,确保在并发环境下数据的一致性和完整性。下面将详细介绍 `synchronized` 的四种主要用法。 1. **修饰实例方法**: 当 `synchronized...

    java_synchronized详解

    通过在方法或代码块上使用`synchronized`,可以确保同一时间只有一个线程能访问这些代码区域,从而有效避免了多线程环境下的数据竞争和不一致性问题。 #### 二、synchronized的作用机制 `synchronized`主要通过对象...

    [JAVA][synchronized的使用]

    `synchronized`关键字在Java中提供了互斥访问,也就是说,当一个线程进入一个对象的`synchronized`代码块或方法时,其他线程对这个对象的`synchronized`代码块或方法的访问将会被阻塞,直到当前线程执行完毕并释放...

    java多线程中synchronized关键字的用法

    java多线程中synchronized关键字的用法 解压密码 www.jiangyea.com

    synchronized用法大全实例

    这些方法必须在同步块或同步方法中使用,否则会抛出`IllegalMonitorStateException`。等待/通知机制可以让一个线程在特定条件下等待,直到其他线程唤醒它。 ### 总结 `synchronized`关键字在Java多线程编程中起到...

    java synchronized demo

    本示例"java synchronized demo"旨在探讨`synchronized`关键字的用法及其作用机制。下面将详细阐述`synchronized`的相关知识点。 1. **synchronized的作用**: - `synchronized`关键字主要用于解决多线程环境中的...

    Java-synchronized详解.docx

    这篇文章将详细介绍 Java 中的 synchronized 机制,通过实例代码,演示如何使用 synchronized解决多线程同步问题。 Java 中的同步机制 在 Java 中,同步机制是通过 synchronized 关键字实现的。synchronized 可以...

    Java synchronized详细解读.docx

    Java中的`synchronized`关键字是多线程编程中用于同步控制的关键元素,它的主要目标是解决并发环境下多个线程对共享资源的访问冲突。在Java中,由于线程共享内存空间,如果没有适当的同步机制,可能会导致数据不一致...

    java-synchronized详解.doc

    Java中的`synchronized`关键字是多线程编程中的一个重要概念,用于控制并发访问共享资源,以保证数据的一致性和完整性。本文将深入解析`synchronized`在Java中的应用和工作原理。 一、`synchronized`的基本用法 `...

    深入理解java中的synchronized关键字

    本文将深入探讨`synchronized`的两种主要用法:synchronized方法和synchronized块。 1. **synchronized 方法** synchronized方法是通过在方法声明前添加`synchronized`关键字来定义的。例如: ```java public ...

    synchronized关键字的用法详解

    在这个示例中,`Thread1`类实现了`Runnable`接口,并在`run`方法中定义了一个`synchronized(this)`代码块。当两个线程`A`和`B`分别启动时,它们都将尝试执行该同步代码块。根据`synchronized`的特性,一次只有一个...

    java关键字Synchronized详解

    总的来说,synchronized是Java中保证线程安全的重要工具,它通过锁机制实现了对共享资源的访问控制,但过度使用或不当使用可能会导致性能下降。理解其工作原理和优化策略,有助于编写高效、线程安全的Java代码。

    生产者消费者Java—synchronized 机制

    这些方法必须在`synchronized`代码块或方法中调用,因为它们依赖于监视器(即对象的锁)来工作。 2. **BlockingQueue(阻塞队列)**:在实际的生产者消费者实现中,通常会使用`java.util.concurrent`包下的`...

    Java中synchronized实现原理详解

    在同步方法中,虽然字节码中没有特定的指令,但会在方法的访问标志中设置`synchronized`,表明这是一个同步方法。 Java对象头是实现锁的关键部分。在Hotspot虚拟机中,对象头包含两部分:Mark Word和Klass Pointer...

Global site tag (gtag.js) - Google Analytics