`
sydra
  • 浏览: 5391 次
  • 性别: Icon_minigender_1
  • 来自: 上海
文章分类
社区版块
存档分类
最新评论

synchronized到底锁了什么(一)

阅读更多
synchronized关键字,需要编写多线程代码的java开发者经常会用到的关键字,它的主要作用是使方法同步,本文将通过一系列测试,希望可以深入解此关键字.
一.synchronized的使用方法.
开始之前,先要搞清楚synchronized字段的使用方法
1.synchronized可以用来声明成员方法,
public synchronized int method () {

}

2.synchronized可以用在代码块中,例如
public void method {
    synchronized(this) {
        dosth();
    }
}

注,括号里必须是一个实例

二.synchronized的作用
下面将开始具体的测试,这次主要测试将synchronized用于声明方法时的主要作用.下面的TestBean.java,这是用户测试的主体类,测试将围绕此类逐步进行.
package org.sluggard.bolg.synctest;

/**
 * 此类为测试的主体类,其中声明了2个动态的同步方法,
 * 2个静态的同步方法,1个动态的非同步方法和1个静态的非同步方法,所有命名为A的方法,
 * 进入方法后会sleep10秒,所有B方法,将只sleep1秒,而所有的非同步方法,将sleep5秒.
 * @author Frank
 *
 */
public class TestBean {
	
	private String dynamicField;
	
	private static String staticField;
	
	/**
	 * 动态的同步方法A
	 * @param value
	 */
	public synchronized void dynamicSyncMethodA(String value) {
		System.out.println("I'm synchronized methodA");
		SleepUtil.sleep(10);
		dynamicField = value;
		System.out.println("Now field is : " + dynamicField);
	}
	
	/**
	 * 动态的同步方法B
	 */
	public synchronized void dynamicSyncMethodB(String value) {
		System.out.println("I'm synchronized methodB");
		SleepUtil.sleep(1);
		dynamicField = value;
		System.out.println("Now field is : " + dynamicField);
	}
	
	/**
	 * 静态同步方法A
	 */
	public static synchronized void staticSyncMethodA(String value) {
		System.out.println("I'm static synchronized methodA");
		SleepUtil.sleep(10);
		staticField = value;
		System.out.println("Now field is : " + staticField);
	}
	
	/**
	 * 静态同步方法B
	 */
	public static synchronized void staticSyncMethodB(String value) {
		System.out.println("I'm static synchronized methodB");
		SleepUtil.sleep(1);
		staticField = value;
		System.out.println("Now field is : " + staticField);
	}
	
	/**
	 * 动态非同步方法
	 */
	public void dynamicUnsyncMethod(String value) {
		System.out.println("I'm dynamic unsynchronized method");
		SleepUtil.sleep(5);
		dynamicField = value;
		System.out.println("Now field is : " + dynamicField);
	}
	
	/**
	 * 静态非同步方法
	 */
	public static void staticUnsyncMethod(String value) {
		System.out.println("I'm static unsynchronized method");
		SleepUtil.sleep(5);
		staticField = value;
		System.out.println("Now field is : " + staticField);
	}
	
}

abstract class SleepUtil {
	public static void sleep(int i){
		try {
			Thread.sleep(i*1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}

下面将针对此类编写测试代码,我们将解决一下一系列问题.
1,synchronized会所住整个类吗?
Test.java,我们为动态方法A和动态方法B分别编写了2个线程类,并分别对2个执行2个实例的synchronized方法.
package org.sluggard.bolg.synctest;

public class Test {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		TestBean testBean1 = new TestBean();
		TestBean testBean2 = new TestBean();
		ThreadDSA dsa = new ThreadDSA(testBean1);
		ThreadDSB dsb = new ThreadDSB(testBean2);
		dsa.start();
		SleepUtil.sleep(1);
		dsb.start();
	}

}

class ThreadDSA extends Thread{

	@Override
	public void run() {
		testBean.dynamicSyncMethodA("DSA");
	}
	
	private TestBean testBean;

	public ThreadDSA(TestBean testBean) {
		super();
		this.testBean = testBean;
	}
}

class ThreadDSB extends Thread{

	@Override
	public void run() {
		testBean.dynamicSyncMethodB("DSB");
	}
	
	private TestBean testBean;
	
	public ThreadDSB(TestBean testBean) {
		super();
		this.testBean = testBean;
	}
}

执行结果如下
引用
I'm synchronized methodA
I'm synchronized methodB
Now field is : DSB
Now field is : DSA

然后,我们将main方法进行修改,改成下面的样子
public static void main(String[] args) {
		
		TestBean testBean = new TestBean();
		ThreadDSA dsa = new ThreadDSA(testBean);
		ThreadDSB dsb = new ThreadDSB(testBean);
		dsa.start();
		SleepUtil.sleep(1);
		dsb.start();
	}

执行结果如下
引用
I'm synchronized methodA
Now field is : DSA
I'm synchronized methodB
Now field is : DSB

答案:synchronized并没有锁住整个类,而是仅仅锁住了某个实例,不同实例中的动态同步方法是不会同步的.
2.当程序进入synchronized方法后,非同步方法可以执行吗?
我们在Test.java中为非同步方法加入一个线程类
class ThreadDUS extends Thread{

	@Override
	public void run() {
		testBean.dynamicUnsyncMethod("DUS");
	}
	
	private TestBean testBean;
	
	public ThreadDUS(TestBean testBean) {
		super();
		this.testBean = testBean;
	}
}

对main方法进行修改
public static void main(String[] args) {
		
		TestBean testBean = new TestBean();
		ThreadDSA dsa = new ThreadDSA(testBean);
		ThreadDUS dus = new ThreadDUS(testBean);
		dsa.start();
		SleepUtil.sleep(1);
		dus.start();
	}

执行结果如下
引用
I'm synchronized methodA
I'm dynamic unsynchronized method
Now field is : DUS
Now field is : DSA

答案:同步锁不会所住非同步的方法,如果你希望2个方法顺序执行,就必须对他们的都枷锁.
3.synchronized会同时锁住动态方法和静态方法吗?
首先,我们先修改一下TestBean,在动态方法中加入对静态成员变量的操作
public synchronized void dynamicSyncMethodA(String value) {
		System.out.println("I'm synchronized methodA");
		SleepUtil.sleep(10);
		dynamicField = value;
		staticField = value;
		System.out.println("Now dynamicfield is : " + dynamicField + "\nNow staticfield is : " + value);
	}

同样,我们为静态同步方法加入线程类,
class ThreadSSA extends Thread{

	@Override
	public void run() {
		TestBean.staticSyncMethodA("SSA");
	}
	
}
class ThreadSSB extends Thread{

	@Override
	public void run() {
		TestBean.staticSyncMethodB("SSB");
	}
	
}

然后修改main方法
public static void main(String[] args) {
		
		TestBean testBean = new TestBean();
		ThreadDSA dsa = new ThreadDSA(testBean);
		ThreadSSB ssb = new ThreadSSB();
		ThreadSSA ssa = new ThreadSSA();
		dsa.start();
		SleepUtil.sleep(1);
		ssb.start();
		ssa.start();
	}

执行结果如下
引用
I'm static synchronized methodB
Now field is : SSB
I'm static synchronized methodA
Now dynamicfield is : DSA
Now staticfield is : DSA
Now field is : SSA

答案:静态方法和动态方法的锁是不同的,动态方法只与动态方法同步,静态方法只与静态方法同步.
三,总结,在动态方法声明中加入synchronized字段,方法将会在运行时获得此对象实例的锁,此实例的所有synchronized方法在锁为释放前将不无法执行,但是其他实例,此实例的非同步方法和静态方法将不受影响.一个类的所有静态方法共享同一把锁.
这是本系列文章的第一篇,主要说明在同一个类中,在声明方法时加入synchronized关键字的作用,以后的文章中,会对synchronized的其他用法,以及多个类之间synchronized关键字的作用进行测试.
分享到:
评论

相关推荐

    java锁机制Synchronizedjava锁机制Synchronized

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

    synchronized枷锁实例

    方法锁是`synchronized`关键字应用于方法的一种形式,它既可以是类锁(用于静态方法),也可以是对象锁(用于非静态方法)。上面的类锁和对象锁示例中,`method()`就是方法锁的体现。 **非公平锁** 在Java中,`...

    Synchronized_锁升级知识点总结

    在Java高并发编程领域,理解Synchronized锁的升级机制是非常重要的。 首先需要知道的是,Synchronized锁在JVM中实现了从低到高的不同锁级别,包括无锁状态、偏向锁状态、轻量级锁状态和重量级锁状态。锁的升级并不...

    正确使用多线程同步锁@synchronized()1

    在Objective-C中,当你使用`@synchronized`块包围一段代码时,会为指定的对象创建一个互斥锁。如果当前线程已经持有了该锁,那么它可以再次获取并执行内部的代码,而不会造成死锁。这种特性使得在嵌套使用`@...

    java 多线程synchronized互斥锁demo

    标题中的"java 多线程synchronized互斥锁demo"指的是一个示例,展示了如何在多线程环境下使用`synchronized`关键字创建互斥锁,确保同一时间只有一个线程可以访问特定的代码块或方法。 描述中的"一个多线程访问的同...

    java 偏向锁、轻量级锁及重量级锁synchronized原理.docx

    Java中的`synchronized`关键字是实现线程安全的关键机制,它基于Java对象头的Mark Word进行锁的状态管理。Mark Word是一个动态变化的数据结构,用于存储对象的HashCode、分代年龄、锁状态标志等信息。在32位JVM中,...

    synchronized锁自旋.docx

    《深入理解synchronized锁自旋机制》 在Java并发编程中,`synchronized`关键字扮演着重要的角色,它提供了一种线程同步机制,确保共享资源在同一时刻只能被一个线程访问。本文将深入探讨`synchronized`锁的内部机制...

    透彻理解Java中Synchronized(对象锁)和Static Synchronized(类锁)的区别

    Synchronized 是一种实例锁,它锁定的是当前对象的实例。也就是说,Synchronized 关键字所修饰的方法或代码块只能被当前对象的实例锁定。这种锁定机制可以防止多个线程同时访问该对象的同一个 synchronized 块。 ...

    lock锁,lock锁和synchronized的对比

    Lock是显式锁,需要手动的开启和关闭,synchronized锁是隐式锁,只要出了作用域就会自动释放。Lock只有代码块锁,synchronized既有代码块锁还有方法锁。 使用Lock锁,JVM将花费较少的时间来调度线程,性能更好。有...

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

    Java synchronized同步锁可以保证同一时刻只有一个线程操作同一资源,使用wait()、notify()切换线程状态保证线程操作的前后顺序实现线程交互。 Java线程状态有五种:新建状态、就绪状态、运行状态、休眠状态和死亡...

    java synchronized 学习

    * 若此对象对应的类中包含了多个 synchronized 修饰的方法或代码块,多个线程访问同一个对象的任意 synchronized 修饰的方法或代码块,只要有一个线程拥有了 synchronized 同步锁,其他线程不管想访问 synchronized ...

    synchronized锁原理分析(一、从Java对象头看synchronized锁的状态)

    《深入剖析synchronized锁原理——从Java对象头的角度》 synchronized关键字在Java中扮演着重要的角色,它是Java实现同步的基础,确保了多线程环境下的数据一致性。不同于基于JDK实现的Lock接口(如ReentrantLock)...

    java中synchronized用法

    Synchronized 关键字的作用是取得对象的锁,而不是把一段代码或函数当作锁。每个对象只有一个锁与之相关联。实现同步是要很大的系统开销作为代价的,甚至可能造成死锁,所以尽量避免无谓的同步控制。 当 ...

    简单聊聊Synchronized和ReentrantLock锁.docx

    本文将深入探讨Synchronized关键字锁和ReentrantLock锁的异同、功能特性以及它们在实际应用中的适用场景。 首先,Synchronized是一种内置的Java关键字,它提供了简单而强大的线程同步机制。当一个线程进入一个由...

    Java synchronized使用案例

    1. **线程互斥**:当一个线程在执行`synchronized`代码时,其他线程必须等待该线程释放锁后才能进入。 2. **内存可见性**:确保线程在读取或修改共享变量时,能看到其他线程对变量的最新修改,避免数据不一致。 3. *...

    volatile和synchronized的区别

    当一个线程访问某个对象的一个`synchronized`方法时,它就获得了该对象的锁,并且其他线程无法再访问该对象的其他`synchronized`方法。 - **互斥性**:通过`synchronized`关键字实现的锁具有互斥性,也就是说,一次...

    java_synchronized详解

    当一个线程进入某个对象的一个`synchronized`代码块时,它会自动获得该对象的锁;离开该代码块时,则自动释放锁。如果其他线程尝试访问同一对象的其他`synchronized`代码块,它们将被阻塞,直到第一个线程释放锁为止...

    synchronized 的理解

    当`synchronized`用于修饰代码块时,需要指定一个锁对象。这使得开发者可以更精细地控制锁的范围,避免不必要的性能损失。 ```java public class MyClass { private Object lock = new Object(); private int ...

    Synchronized关键字的用法

    - **锁机制**:当一个线程进入`synchronized`代码块或方法时,会自动获取锁;离开时,自动释放锁。 - **互斥性**:同一时刻,只有一个线程可以拥有锁,其他试图获取锁的线程将被阻塞,直到锁被释放。 - **锁升级**:...

    Java并发 synchronized锁住的内容解析

    Java并发synchronized锁住的内容解析是Java并发编程中的一种重要机制,用于解决多线程并发访问同一个资源时可能出现的线程安全问题。通过使用synchronized关键字,可以锁住当前对象的当前方法,使得其他线程访问该...

Global site tag (gtag.js) - Google Analytics