`

Java之synchronized深入应用

    博客分类:
  • Java
阅读更多
参考资料
1 java synchronized详解
http://www.cnblogs.com/GnagWang/archive/2011/02/27/1966606.html
2 Java线程:并发协作-生产者消费者模型
http://lavasoft.blog.51cto.com/62575/221932
这篇文章说得相当不错呀,推荐呀
java关键字: synchronized,它包括两种用法:synchronized 方法和 synchronized 块.
它用来修饰一个方法或者一个代码块时,保证在同一时刻最多只有一个线程执行该段代码,
一、当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。
二、然而,当一个线程访问object的一个synchronized(this)同步代码块时,另一个线程仍然可以访问该object中的非synchronized(this)同步代码块。
三、尤其关键的是,当一个线程访问object的一个synchronized(this)同步代码块时,其他线程对object中所有其它synchronized(this)同步代码块的访问将被阻塞。
四、第三个例子同样适用其它同步代码块。也就是说,当一个线程访问object的一个synchronized(this)同步代码块时,它就获得了这个object的对象锁。结果,其它线程对该object对象所有同步代码部分的访问都被暂时阻塞。
五、以上规则对其它对象锁同样适用.

synchronized 方法的缺陷:若将一个大的方法声明为synchronized 将会大大影响效率,推荐使用,synchronized 块
synchronized 块:通过 synchronized关键字来声明synchronized 块。语法如下:
synchronized(syncObject) { 
//允许访问控制的代码 
} 

synchronized 块是这样一个代码块,其中的代码必须获得对象 syncObject的锁方能执行,由于可以针对任意代码块,且可任意指定上锁的对象,故灵活性较高.
示例如下:请参见注释
package net.liuzd.thread.synchronizeds;

public class ThreadSynchronized {

	
	public static void main(String[] args) {

		new ThreadSynchronized().init();

	}

	private void init() {

		final OutPut op = new OutPut();

		new Thread(new Runnable() {

			@Override
			public void run() {

				while (true) {
					try {
						Thread.sleep(10);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					op.output("abcdefghi");
				}
			}

		}).start();

		new Thread(new Runnable() {

			@Override
			public void run() {

				while (true) {
					try {
						Thread.sleep(10);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					op.output("123456789");
				}
			}

		}).start();

	}

	class OutPut {
		
		private String test = "";

		public void output(String name) {
			//产生问题所在:A线程与B线程用的不是同一个字符串对象,因为name这个字符串会发生变化,所以这样设置还是不行的,始终使用的是同一个对象才能起到互斥的效果
			/*synchronized(name){
				for (char c : name.toCharArray()) {
					System.out.print(c);
				}
				System.out.println();
			}*/
			//所以作如下修改,声明一个局部变量作互斥效果
			synchronized(test){
				for (char c : name.toCharArray()) {
					System.out.print(c);
				}
				System.out.println();
			}
			//通过这样的设置就解决这个问题了
			
			//或者是以下这种方式
			/*synchronized(this){
				for (char c : name.toCharArray()) {
					System.out.print(c);
				}
				System.out.println();
			}*/			
			
		}
	}
}

package net.liuzd.thread.synchronizeds;

public class ThreadSynchronized2 {

	/**
	 * @param args
	 */
	public static void main(String[] args) {

		new ThreadSynchronized2().init();

	}

	private void init() {

		final OutPut op = new OutPut();

		new Thread(new Runnable() {

			@Override
			public void run() {

				while (true) {
					try {
						Thread.sleep(10);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					op.output("abcdefghi");
				}
			}

		}).start();

		new Thread(new Runnable() {

			@Override
			public void run() {

				while (true) {
					try {
						Thread.sleep(10);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				 //op.output("123456789");
					//如果我们这里重新实例化一个对象来调用的话,那么将会产生不同步的状况了
					new OutPut().output("123456789");
					
				}
			}

		}).start();

	}

	class OutPut {
		

		public void output(String name) {
			
			/*synchronized(this){
				for (char c : name.toCharArray()) {
					System.out.print(c);
				}
				System.out.println();
			}
			*/
			
			//在内存中类的二进制代码始终保持一致的
			synchronized(OutPut.class){
				for (char c : name.toCharArray()) {
					System.out.print(c);
				}
				System.out.println();
			}
			
			
		}
	}
}

package net.liuzd.thread.synchronizeds;

public class ThreadSynchronized3 {

	
	public static void main(String[] args) {

		new ThreadSynchronized3().init();

	}

	private void init() {

		final OutPut op = new OutPut();

		new Thread(new Runnable() {

			@Override
			public void run() {

				while (true) {
					try {
						Thread.sleep(10);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					op.output("abcdefghi");
				}
			}

		}).start();

		new Thread(new Runnable() {

			@Override
			public void run() {

				while (true) {
					try {
						Thread.sleep(10);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				 op.output2("123456789");
				
										
				}
			}

		}).start();

	}

	class OutPut {
		

		public void output(String name) {
					
			//在内存中类的二进制代码始终保持一致的
			//用OutPut.class不能进行互斥
			synchronized(this){
				for (char c : name.toCharArray()) {
					System.out.print(c);
				}
				System.out.println();
			}
			
			
		}
		
		//方法上用的同步指的是this对象,那么和第一个方法用的是同一把锁
		public synchronized void output2(String name) {			
					
				for (char c : name.toCharArray()) {
					System.out.print(c);
				}
				System.out.println();
		}
	}
}

package net.liuzd.thread.synchronizeds;

public class ThreadSynchronized4 {


	public static void main(String[] args) {

		new ThreadSynchronized4().init();

	}

	private void init() {

		final OutPut op = new OutPut();

		new Thread(new Runnable() {

			@Override
			public void run() {

				while (true) {
					try {
						Thread.sleep(10);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					op.output("abcdefghi");
				}
			}

		}).start();

		new Thread(new Runnable() {

			@Override
			public void run() {

				while (true) {
					try {
						Thread.sleep(10);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					new OutPut().output2("123456789");
				    //如果我们这里重新实例化一个对象来调用的话,那么将会产生不同步的状况了
				    //因为重新实例化一个对象在内存的字节码是不一样,这样线程也不会进行互斥了
				    //解决方式是声明类为静态的
										
				}
			}

		}).start();

	}

	static class OutPut {
		

		public void output(String name) {
					
			
			//用OutPut.class,this不能进行互斥
			synchronized(OutPut.class){
				for (char c : name.toCharArray()) {
					System.out.print(c);
				}
				System.out.println();
			}
			
			
		}
		
		
		public static synchronized void output2(String name) {			
					
				for (char c : name.toCharArray()) {
					System.out.print(c);
				}
				System.out.println();
		}
	}
}

package net.liuzd.thread.synchronizeds;

public class ThreadSynchronized5 {

	
	public static void main(String[] args) {

		new ThreadSynchronized5().init();

	}

	private void init() {

		final OutPut op = new OutPut();

		new Thread(new Runnable() {

			@Override
			public void run() {

				while (true) {
					try {
						Thread.sleep(10);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					op.output("abcdefghi");
					//op.output2("abcdefghi");
					//用output2与output3不能进行互斥效果
					
				}
			}

		}).start();

		new Thread(new Runnable() {

			@Override
			public void run() {

				while (true) {
					try {
						Thread.sleep(10);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					op.output3("123456789"); 				  
										
				}
			}

		}).start();

	}

	static class OutPut {
		

		public void output(String name) {
					
			//用OutPut.class与output3可以进行互斥效果
			//用this与output2可以进行互斥效果
			
			synchronized(OutPut.class){
				for (char c : name.toCharArray()) {
					System.out.print(c);
				}
				System.out.println();
			}
			
			
		}
		public  synchronized void output2(String name) {			
			
			for (char c : name.toCharArray()) {
				System.out.print(c);
			}
			System.out.println();
	  }
		
		
		
		
		public static synchronized void output3(String name) {			
					
				for (char c : name.toCharArray()) {
					System.out.print(c);
				}
				System.out.println();
		}
	}
}

synchronized总结如下
一  无论synchronized关键字加在方法上还是对象上,它取得的锁都是对象,而不是把一段代码或函数当作锁――而且同步方法很可能还会被其他线程的对象访问。
二.每个对象只有一个锁(lock)与之相关联。
三.实现同步是要很大的系统开销作为代价的,甚至可能造成死锁,所以尽量避免无谓的同步控制.


分享到:
评论

相关推荐

    [JAVA][synchronized的使用]

    本篇文章将深入探讨`synchronized`的使用,包括其基本原理、使用方式以及实际应用场景。 1. **synchronized的基本原理** `synchronized`关键字在Java中提供了互斥访问,也就是说,当一个线程进入一个对象的`...

    深入理解Java中的synchronized关键字:同步机制与应用

    在多线程编程中,确保线程安全是至关重要的。Java提供了多种机制来处理并发问题,其中synchronized...通过深入理解synchronized关键字,开发者可以更好地处理Java中的并发问题,构建出更加健壮和高效的多线程应用程序。

    Java synchronized详细解读.docx

    首先,`synchronized`可以应用于两种情况:同步方法和同步代码块。同步方法是通过在方法声明前加上`synchronized`关键字,例如`public synchronized void method() {...}`。同步代码块则是通过`synchronized`关键字...

    深入理解java中的synchronized关键字

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

    java基本教程之synchronized关键字java多

    本教程将深入讲解`synchronized`关键字及其在Java多线程中的应用。 一、synchronized关键字的作用与原理 `synchronized`关键字主要有两个作用:同步方法和同步块。它通过锁机制来实现线程同步,防止多个线程同时...

    java-synchronized详解.doc

    本文将深入解析`synchronized`在Java中的应用和工作原理。 一、`synchronized`的基本用法 `synchronized`可以应用于方法或代码块。当它修饰一个方法时,整个方法被视为同步的,只有一个线程可以执行该方法。当修饰...

    深入理解Java并发之synchronized实现原理.docx

    Java并发编程中的synchronized关键字是实现线程安全的重要工具,它提供了一种互斥访问机制,确保了共享数据在同一时刻只能被一个线程访问。synchronized关键字有三种主要的应用方式: 1. 修饰实例方法:当...

    Java程序设计 Java设计与应用

    《Java程序设计与应用》是张仕斌先生的著作,是一部深入浅出的Java学习教程。这本书涵盖了Java程序设计的基础到高级应用,旨在帮助读者掌握Java编程的核心技能,并能将其应用于实际开发中。以下是该书可能涉及的一些...

    Java程序设计及应用开发教程

    Java程序设计及应用开发教程是面向初学者和进阶者的一门重要课程,旨在深入讲解Java编程语言的基础知识以及在实际应用中的开发技巧。通过这门教程,学习者可以掌握如何利用Java进行高效、可靠的软件开发。 首先,...

    Java程序设计与应用开发(第2版)

    2. **面向对象编程**:深入讲解类、对象、封装、继承、多态等核心概念,这是Java编程的基础,也是理解和应用其他高级特性的前提。 3. **控制结构**:涵盖if语句、switch语句、循环(for、while、do-while)等,以及...

    Java程序设计与应用开发课件

    Java程序设计与应用开发是计算机科学中的核心课程之一,它主要教授如何使用Java语言进行高效、可靠的软件开发。本课件旨在提供一个全面的Java学习框架,覆盖了从基础语法到高级特性的各个方面,帮助学生和开发者深入...

    Java并发编程系列- synchronized

    本篇文章将深入探讨`synchronized`的使用及其在Java并发编程中的作用。 首先,`synchronized`关键字的主要功能是实现线程同步,确保同一时间只有一个线程可以执行特定的代码段。这在处理共享数据时尤为重要,因为它...

    java帮助和web应用

    综上所述,这份文档不仅覆盖了Java编程的基础知识,还深入介绍了Web开发的技术要点,并结合实际案例提供了丰富的实战经验和工具资源推荐,非常适合希望深入学习Java及Web应用开发的学习者和开发者们参考。

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

    在Java编程语言中,线程(Thread)、同步(synchronized)和并发(Concurrency)是核心概念,它们在多任务处理和高效系统设计中扮演着重要角色。本文将深入探讨这三个主题,以及它们如何相互作用以确保程序的正确性...

    Android synchronized 测试案例

    在Android开发中,`synchronized`关键字是Java语言中用于实现线程...通过这个测试案例,开发者可以深入理解`synchonized`关键字在Android应用程序中的应用,从而编写出更健壮的多线程代码,提升应用的稳定性和性能。

    QTS青训-java8 高级应用与开发 实验答案

    这些实验答案提供了对Java 8新特性的实践操作,可以帮助开发者深入理解和掌握这些关键知识点。虽然可能与书本上的习题略有差异,但大体思路和解题方法相似,是巩固理论知识和提高编程技能的宝贵资源。在实际学习过程...

    java程序设计及应用开发实验题源代码.rar

    每个实验都是一个具体场景的应用,通过实践这些实验,你将能更深入地理解Java语言特性和开发流程。 此外,调试技巧也是学习过程中不可或缺的部分,学会使用IDE(如Eclipse或IntelliJ IDEA)的调试工具,可以帮助你...

    \Java应用开发教程

    同时,结合"java数据库服务器程序设计"这个标签,我们可以深入探讨如何使用Java与数据库进行交互,比如JDBC(Java Database Connectivity)的使用,以及如何设计和实现数据库服务器应用程序。 首先,Java作为一种强...

    Java使用synchronized修饰方法来同步线程的实例演示

    本文将深入探讨synchronized修饰方法在Java中的使用及其工作原理,并通过实例演示其应用。 1. **synchronized原理** synchronized基于Java的内置锁(也称为对象锁或 monitors)机制。当一个线程进入synchronized...

Global site tag (gtag.js) - Google Analytics