`
qtlkw
  • 浏览: 307342 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

synchronized example

阅读更多
参照:http://azrael6619.iteye.com/blog/425630
一、同步方法
public synchronized void A(){
  //...
}
锁定的是调用这个同步方法的对象

测试:
a、不使用这个关键字修饰方法,两个线程调用同一个对象的这个方法。
目标类:
public class BusinessLogic{
	public void execute(){
		for(int i=0; i<100; i++){
			System.out.println(Thread.currentThread().getName() +":" + i);
		}
	}
}

线程类:
public class RunnableImpl implements Runnable{
	BusinessLogic thread = null;
	public RunnableImpl(BusinessLogic thread){
		this.thread = thread;
	}
	
	public void run(){
		thread.execute();
	}
}

调用:
public class Main {
	public static void main(String[] args) throws Exception{
		BusinessLogic test = new BusinessLogic();
		Runnable runnable = new RunnableImpl(test);
		Thread a = new Thread(runnable, "A");
		a.start();
		
		Thread b = new Thread(runnable, "B");
		b.start();
	}
}

结果:
输出的数字交错在一起。说明不是同步的,两个方法在不同的线程中是异步调用的。

b、修改目标类,增加synchronized修饰:
public class BusinessLogic {
	public synchronized void execute(){
		for(int i=0; i<100; i++){
			System.out.println(Thread.currentThread().getName() +":" + i);
		}
	}
}


结果:
输出的数字是有序的,首先输出A的数字,然后是B,说明是同步的,虽然是不同的线程,但两个方法是同步调用的。
注意:上面虽然是两个不同的线程,但是是同一个实例对象。下面使用不同的实例对象进行测试。


c、每个线程都有独立的TestThread对象。
目标类:
public class BusinessLogic {
	public synchronized void execute(){
		for(int i=0; i<100; i++){
			System.out.println(Thread.currentThread().getName() +":" + i);
		}
	}
}

调用:
public class Main {
	public static void main(String[] args) throws Exception{
		BusinessLogic test = new BusinessLogic();
		Runnable runnable = new RunnableImpl(test);
		Thread a = new Thread(runnable, "A");
		a.start();
		
		
		BusinessLogic test2 = new BusinessLogic();
		Runnable runnable2 = new RunnableImpl(test2);
		Thread b = new Thread(runnable2, "B");
		b.start();
	}
}

结果:
输出的数字交错在一起。说明虽然增加了synchronized 关键字来修饰方法,但是不同的线程调用各自的对象实例,两个方法仍然是异步的。

引申:
对于这种多个实例,要想实现同步即输出的数字是有序并且按线程先后顺序输出,我们可以增加一个静态变量,对它进行加锁(后面将说明锁定的对象)。

修改目标类:
public class BusinessLogic {
	private static Object lock = new Object(); //It must be a static Object
	public void execute(){
		synchronized(lock){
			for(int i=0; i<100; i++){
				System.out.println(Thread.currentThread().getName() +":" + i);
			}
		}
	}
}


二、同步代码块
锁定一个对象,其实锁定的是该对象的引用(object reference)
谁拿到这个锁谁就可以运行它所控制的那段代码。当有一个明确的对象作为锁时,就可以按上面的代码写程序,但当没有明确的对象作为锁,只是想让一段代码同步时,可以创建一个特殊的instance变量(它必须是一个对象)来充当锁(上面的解决方法就是增加了一个状态锁)。
a、锁定一个对象,它不是静态的
public class BusinessLogic {
	private Object lock=new Object(); // It is not a static Object
	public void execute(){
		synchronized(lock){ //增加了个锁,锁定了对象lock,在同一个类实例中,是线程安全的,但不同的实例还是不安全的。因为不同的实例有不同对象锁lock
			for(int i=0; i<100; i++){
				System.out.println(Thread.currentThread().getName() +":" + i);
			}
		}
	}
}


其实上面锁定一个方法,等同于下面的:
public void execute(){
		synchronized(this){
			for(int i=0; i<100; i++){
				System.out.println(Thread.currentThread().getName() +":" + i);
			}
		}
	}

b、锁定一个对象或方法,它是静态的
这样锁定,它锁定的是对象所属的类
public class BusinessLogic {
	public synchronized static void execute(){
		for(int i=0; i<100; i++){
			System.out.println(Thread.currentThread().getName() +":" + i);
		}
	}
}

等同于:
public class BusinessLogic {
	private static Object lock = new Object(); //It must be a static Object
	public void execute(){
		synchronized(lock){
			for(int i=0; i<100; i++){
				System.out.println(Thread.currentThread().getName() +":" + i);
			}
		}
	}
}


c、注意:
1、用synchronized 来锁定一个对象的时候,如果这个对象在锁定代码段中被修改了,则这个锁也就消失了。看下面的实例:

目标类:
public class BusinessLogic {
	private static Object lock = new Object();
	public void execute(){
		synchronized(lock){
			lock = "abc";
			for(int i=0; i<100; i++){
				System.out.println(Thread.currentThread().getName() +":" + i);
			}
		}
	}
}

调用:
public class Main {
	public static void main(String[] args) throws Exception{
		BusinessLogic test = new BusinessLogic();
		Runnable runnable = new RunnableImpl(test);
		Thread a = new Thread(runnable, "A");
		a.start();
		
		
		BusinessLogic test2 = new BusinessLogic();
		Runnable runnable2 = new RunnableImpl(test2);
		Thread b = new Thread(runnable2, "B");
		b.start();
	}
}

不注释lock = "abc";输出是无序得。

同理:
目标类:
public class BusinessLogic {
	private Object lock = new Object();
	public void execute(){
		synchronized(lock){
			lock = "abc";
			for(int i=0; i<100; i++){
				System.out.println(Thread.currentThread().getName() +":" + i);
			}
		}
	}
}

调用:
public class Main {
	public static void main(String[] args) throws Exception{
		BusinessLogic test = new BusinessLogic();
		Runnable runnable = new RunnableImpl(test);
		Thread a = new Thread(runnable, "A");
		a.start();
		
		Thread b = new Thread(runnable, "B");
		b.start();
	}
}

除非lock = "abc"被注释,否则输出为无序。
分享到:
评论

相关推荐

    synchronized关键字的用法详解

    public class Example { private int value; public synchronized void accessVal(int newVal) { value = newVal; // 其他代码 } } ``` 这里,`accessVal`方法被声明为`synchronized`。这意味着每次只有一个...

    同步代码块(synchronized).zip

    在Java编程语言中,同步代码块(synchronized blocks)是一种重要的多线程控制机制,用于保证线程安全,防止数据的不一致性。本压缩包包含了两个示例代码——Example12.java和Example13.java,它们是针对同步代码块...

    Lock接口与synchronized关键字

    public class LockExample { private final ReentrantLock lock = new ReentrantLock(); public void doSomething() { lock.lock(); try { // 执行需要同步的代码 System.out.println("执行同步代码"); } ...

    JavaExample例子源程序

    6. **多线程**:Java内置对多线程的支持,你可以看到如何创建线程,使用同步机制(如`synchronized`关键字和`wait()`, `notify()`方法)来避免线程并发问题。 7. **接口与抽象类**:接口和抽象类是实现多态性的重要...

    JavaExample

    6. **多线程**:Java提供了对并发编程的良好支持,例子可能包括Thread类的使用,Runnable接口,synchronized关键字,以及线程池的创建和管理。 7. **网络编程**:如Socket编程,HTTP请求等,这对于开发网络应用的...

    多线程的example

    本示例“多线程的example”旨在探讨如何在Java中实现和管理多线程,尤其是关于锁(lock)和同步(synchronized)的概念。 一、线程的创建与运行 在Java中,有两种主要的创建线程的方式: 1. 继承`java.lang.Thread...

    JAVA code example 100 例

    在本资源"JAVA code example 100 例"中,我们拥有一系列精心挑选的Java编程示例,旨在帮助开发者深入理解和应用Java语言。这个压缩包包含了从基础到高级的100个源代码实例,覆盖了Java编程的多个重要方面。下面,...

    java多线程编程之Synchronized块同步方法

    在上述代码中,`Example`类有一个`synchronized`修饰的`excute()`方法。这意味着当一个线程正在执行`excute()`方法时,其他试图进入该方法的线程将会被阻塞,直到当前线程完成执行并释放锁。因此,当`Thread1`和`...

    Java 多线程synchronized关键字详解(六)

    由于它们都被`synchronized`修饰,这意味着尽管`execute()`和`execute2()`是不同的方法,但是它们仍然共享相同的锁,即`Example`对象本身。因此,即使有多个线程(如`Thread1`和`Thread2`)分别调用这两个方法,它们...

    java_100_example.rar_java eclipse example

    6. **多线程**:了解Thread类,实现Runnable接口,线程同步(synchronized关键字,wait(),notify(),notifyAll())和线程池的使用。 7. **反射机制**:通过反射动态获取类信息,创建对象,调用方法,访问字段。 8...

    sun java的课件的原版demo,example etc.

    例子将展示如何创建和管理线程,以及如何使用synchronized关键字和wait/notify机制来处理并发问题。 9. **Java Swing和JavaFX**:这两个是Java的图形用户界面库,用于构建桌面应用。示例可能包含创建窗口、按钮、...

    java-Example-21-30.rar_example 30

    在本压缩包“java-Example-21-30.rar_example 30”中,包含的是Java编程语言的实用示例代码,涵盖了从第21个到第30个实例。这些实例旨在帮助开发者深入理解和掌握Java编程的核心概念与技术。通过对这些例子的学习,...

    java同步互斥信号量问题

    SemaphoreExample example = new SemaphoreExample(); Thread thread1 = new Thread(() -&gt; example.criticalSection()); Thread thread2 = new Thread(() -&gt; example.criticalSection()); thread1.start(); ...

    course-java-basic-example-master.zip

    7. **多线程**:学习如何创建和管理线程,理解同步和互斥的概念,以及使用synchronized关键字和wait/notify机制。 8. **异常处理**:学习Java的异常处理机制,如何抛出和捕获异常。 9. **泛型**:理解泛型的作用,...

    pipeline_example:pipeline_example

    Java提供了ExecutorService、Thread、synchronized关键字等工具来处理并发问题。 4. **设计模式**:如工厂模式、观察者模式等,可以用于创建和管理pipeline中的组件,以及处理数据变化的事件。 5. **函数式编程**...

    svg_example

    4. **动画**:SVG支持通过`&lt;animate&gt;`元素或SMIL(Synchronized Multimedia Integration Language)来创建动画效果。 5. **JavaScript交互**:通过JavaScript,可以动态地修改SVG元素的属性,实现交互式图形。例如,...

    java-core-learning-example-master.zip

    5. **多线程(Multithreading)**:Java内核支持多线程编程,提供了Thread类和Runnable接口,以及同步控制机制如synchronized关键字、wait()、notify()和notifyAll()方法。 6. **反射(Reflection)**:Java反射允许...

    core-Java-volume1--example-code.rar_core java 1 code

    在示例代码中,你可以看到如何创建和管理线程,以及如何使用同步机制(如synchronized关键字和Lock接口)来避免线程安全问题。 最后,反射和注解是Java的高级特性。反射允许程序在运行时动态地获取类的信息并操作类...

    java-Example-31-40.rar_40

    "java-Example-31-40.rar_40"这个压缩包包含了一组实用的Java编程示例,涵盖了从第31个到第40个例子,这些都是在实际开发中可能会遇到的常见问题和解决方案。下面,我们将深入探讨这些实例,提取出重要的知识点,以...

Global site tag (gtag.js) - Google Analytics