现在的位置: 首页 > 综合 > 正文

synchronized详解

2018年02月18日 ⁄ 综合 ⁄ 共 3788字 ⁄ 字号 评论关闭

synchronized详解:

被它修饰的代码块或方法,能够保证同一时间只能有一个线程执行该段代码.

一、当两个并发线程访问同一个对象object的synchronized(this)同步代码块/同步方法的时候,另一个线程仍可以访问该object的非同步代码块/非同步方法。

package com.syn;

public class synTest {
	public static void main(String[] args) {
		final SynObj so = new SynObj();
		Thread t1 = new Thread(new Runnable() {
			public void run() {
				so.methodOne();
			}
		});
		
		Thread t2 = new Thread(new Runnable(){
			public void run(){
				so.methodTwo();
			}
		});
		
		t1.start();
		t2.start();
	}
}

class SynObj extends Thread{
	public synchronized void methodOne(){
		int count = 5;
		while(count > 0){
			System.out.println(Thread.currentThread().getName() + " " + count--);
		}
	}
	
	public void methodTwo(){
		int count = 5;
		while(count > 0){
			System.out.println(Thread.currentThread().getName() + " " + count--);
		}
	}
}

输出:

Thread-1 5
Thread-1 4
Thread-2 5
Thread-1 3
Thread-2 4
Thread-1 2
Thread-2 3
Thread-1 1
Thread-2 2
Thread-2 1

二、当两个并发线程中的一个访问某个object的synchronized(this)同步代码块/同步方法的时候,另外一个线程如果要访问该object的synchronized(this)代码块/方法就会被阻塞。

如果我们将上面代码的methodTwo加上synchronized,或者声明为同步代码块:

public synchronized void methodTwo(){
	int count = 5;
	while(count > 0){
		System.out.println(Thread.currentThread().getName() + " " + count--);
	}
}

public void methodTwo(){
	synchronized(this){
	        int count = 5;
		while(count > 0){
			System.out.println(Thread.currentThread().getName() + " " + count--);
		}
	}
}

那么输出就为:

Thread-1 5
Thread-1 4
Thread-1 3
Thread-1 2
Thread-1 1
Thread-2 5
Thread-2 4
Thread-2 3
Thread-2 2
Thread-2 1

synchronized 方法和 synchronized 块:

1.synchronized 方法

每个类实例都有一个锁,每个synchronized方法只有在获得调用该方法的实例的锁之后才能执行,否则该线程阻塞,方法一旦执行,就独占该锁,直至方法退出。这种机制保证了同一个时刻对于每一个类实例,在所有声明为synchronized的成员函数中至多只有一个处于执行状态,(因为至多只有一个能够获得该类实例对应的锁),从而有效避免了类成员变量的访问冲突(只要所有可能访问类成员变量的方法均被声明为 synchronized)。

在 Java 中,不光是类实例,每一个类也对应一把锁,这样我们也可将类的静态成员函数声明为 synchronized ,以控制其对类的静态成员变量的访问。  

synchronized 方法的缺陷:若将一个大的方法声明为synchronized 将会大大影响效率,典型地,若将线程类的方法 run() 声明为synchronized ,由于在线程的整个生命期内它一直在运行,因此将导致它对本类任何 synchronized 方法的调用都永远不会成功。

2.synchronized 块:

通过 synchronized关键字来声明synchronized 块。语法如下: 
synchronized(syncObject) { 
         //允许访问控制的代码 

synchronized 块是这样一个代码块,其中的代码必须获得对象 syncObject (如前所述,可以是类实例或类)的锁方能执行。

synchronized详解:

被它修饰的代码块或方法,能够保证同一时间只能有一个线程执行该段代码.

一、当两个并发线程访问同一个对象object的synchronized(this)同步代码块/同步方法的时候,另一个线程仍可以访问该object的非同步代码块/非同步方法。

package com.syn;

public class synTest {
	public static void main(String[] args) {
		final SynObj so = new SynObj();
		Thread t1 = new Thread(new Runnable() {
			public void run() {
				so.methodOne();
			}
		});
		
		Thread t2 = new Thread(new Runnable(){
			public void run(){
				so.methodTwo();
			}
		});
		
		t1.start();
		t2.start();
	}
}

class SynObj extends Thread{
	public synchronized void methodOne(){
		int count = 5;
		while(count > 0){
			System.out.println(Thread.currentThread().getName() + " " + count--);
		}
	}
	
	public void methodTwo(){
		int count = 5;
		while(count > 0){
			System.out.println(Thread.currentThread().getName() + " " + count--);
		}
	}
}

输出:

Thread-1 5
Thread-1 4
Thread-2 5
Thread-1 3
Thread-2 4
Thread-1 2
Thread-2 3
Thread-1 1
Thread-2 2
Thread-2 1

二、当两个并发线程中的一个访问某个object的synchronized(this)同步代码块/同步方法的时候,另外一个线程如果要访问该object的synchronized(this)代码块/方法就会被阻塞。

如果我们将上面代码的methodTwo加上synchronized,或者声明为同步代码块:

public synchronized void methodTwo(){
	int count = 5;
	while(count > 0){
		System.out.println(Thread.currentThread().getName() + " " + count--);
	}
}

public void methodTwo(){
	synchronized(this){
	        int count = 5;
		while(count > 0){
			System.out.println(Thread.currentThread().getName() + " " + count--);
		}
	}
}

那么输出就为:

Thread-1 5
Thread-1 4
Thread-1 3
Thread-1 2
Thread-1 1
Thread-2 5
Thread-2 4
Thread-2 3
Thread-2 2
Thread-2 1

synchronized 方法和 synchronized 块:

1.synchronized 方法

每个类实例都有一个锁,每个synchronized方法只有在获得调用该方法的实例的锁之后才能执行,否则该线程阻塞,方法一旦执行,就独占该锁,直至方法退出。这种机制保证了同一个时刻对于每一个类实例,在所有声明为synchronized的成员函数中至多只有一个处于执行状态,(因为至多只有一个能够获得该类实例对应的锁),从而有效避免了类成员变量的访问冲突(只要所有可能访问类成员变量的方法均被声明为 synchronized)。

在 Java 中,不光是类实例,每一个类也对应一把锁,这样我们也可将类的静态成员函数声明为 synchronized ,以控制其对类的静态成员变量的访问。  

synchronized 方法的缺陷:若将一个大的方法声明为synchronized 将会大大影响效率,典型地,若将线程类的方法 run() 声明为synchronized ,由于在线程的整个生命期内它一直在运行,因此将导致它对本类任何 synchronized 方法的调用都永远不会成功。

2.synchronized 块:

通过 synchronized关键字来声明synchronized 块。语法如下: 
synchronized(syncObject) { 
         //允许访问控制的代码 

synchronized 块是这样一个代码块,其中的代码必须获得对象 syncObject (如前所述,可以是类实例或类)的锁方能执行。

抱歉!评论已关闭.