`

Synchronized

阅读更多
Synchronized


一、锁重入
1.概念

关键字 synchronized 拥有锁重入功能,也就是在使用 synchronized 时,当一个线程得到了一个对象的锁后,再次请求此对象时可以再次得到该对象的锁。

2.示例

三个方法,依次调用,获取 第一个方法的锁,执行第二个方法时同样可以获取锁

package com.study.current.thread.day01;

/**
 * 锁重入的机制
 * 在获取 m1 的锁后获取 m2 的锁
 */
public class SynchronizedDubo1 extends Thread {

	public synchronized void method1(){
		System.out.println("method1");
		method2();
	}
	
	public synchronized void method2(){
		System.out.println("method2");
		method3();
	}
	
	public synchronized void method3(){
		System.out.println("method3");
	}
	
	
	/**
	 * @param args
	 */
	public static void main(String[] args) {

		final SynchronizedDubo1 thread = new SynchronizedDubo1();
		Thread t = new Thread(new Runnable() {
			
			public void run() {
				thread.method1();
			}
		});
		t.start();
	}

}



二、父子类

父子类间继承时,使用synchronized 保证线程安全
package com.study.current.thread.day01;

/**
 * 父子关系调用
 */
public class SynchronizedDubo2 extends Thread {

	static class Main{
		public int i = 10 ;
		public synchronized void operationSup(){
			i -- ;
			System.out.println("Main i : "+i);
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		} 
		
	}
	
	static class SubMain extends Main{
		public synchronized void operationSub(){
			while(i> 0){
				i -- ;
				System.out.println("SubMain i : "+i);
				try {
					Thread.sleep(1000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				this.operationSup();
			}
		}
	}
	
	
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		
		Thread thread = new Thread(new Runnable() {
			
			public void run() {
				SubMain syn = new SubMain();
				syn.operationSub();
			}
		});
		thread.start();
	}

}



三、异常

当发生异常时,或中断运行(异常数据对后续功能有影响),或继续运行但保存错误数据的日志

package com.study.current.thread.day01;

public class SynchronizedException extends Thread {

	public int count = 0 ;
	
	/**
	 * 注意此处的捕获异常,级别为 Exception 即可以捕获此时的两种 Exception
	 * 执行结果:出现异常,但程序依然在运行
	 */
	public synchronized void operation(){
		while(true){
			count ++ ;
			try {
				Thread.sleep(1000);
				System.out.println(Thread.currentThread().getName()+" count : "+count);
				if(count == 10){
					System.out.println(Integer.valueOf("a"));
				}
			} catch (Exception e) {
				e.printStackTrace();
				System.out.println("log log 10 exception");
			}
		}
	}
	
	/**
	 * @param args
	 */
	public static void main(String[] args) {

		final SynchronizedException exc = new SynchronizedException();
		
		Thread t = new Thread(new Runnable() {
			
			public void run() {
				exc.operation();
			}
		},"t1");
		
		t.start();
	}

}



四、锁种类

使用 synchronized 声明的方法在某些情况下是由弊端的,比如A线程调用同步的方法执行一个很长时间的任务,那么B线程就必须等待比较长的时间才能执行,这样的情况下可以使用 synchronized 代码块去优化代码执行时间,即减小锁的粒度


锁:
当前对象作为锁
类作为锁
任意对象作为锁
package com.study.current.thread.day01;

/**
 * 锁对象
 * 1.当前对象锁
 * 2.类锁
 * 3.任意对象锁
 */
public class ObjectLock extends Thread {

	public void method1(){
		synchronized (this) { // 对象锁,this 指代当前对象
			System.out.println("method1");
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
	
	public void method2(){
		synchronized (ObjectLock.class) {
			System.out.println("method2"); // 类锁
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
	
	private Object ojt = new Object();
	public void method3(){
		synchronized (ojt) { // 任意对象锁
			System.out.println("method3");
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
	
	/**
	 * @param args
	 */
	public static void main(String[] args) {

		final ObjectLock lock = new ObjectLock();
		Thread t1 = new Thread(new Runnable() {
			
			public void run() {
				lock.method1();
			}
		});
		
		Thread t2 = new Thread(new Runnable() {
			
			public void run() {

				lock.method2();
			}
		});
		
		Thread t3 = new Thread(new Runnable() {
			
			public void run() {
				lock.method3();
			}
		});
		
		t1.start();
		t2.start();
		t3.start();
	}

}



五、String 常量不能作为锁

String 常量作为锁,会造成死循环,锁失效
package com.study.current.thread.day01;

/**
 * String 常量作为锁,会出现死循环
 */
public class StringLock {

	public void method(){
		/**
		 * 使用字符串常量当做锁,会出现死循环,即当前的运行结果总是  t1 的线程
		 * 字符串常量只有一个引用
		 * 解决:
		 * 可以替换为 new String("") 
		 */
		synchronized ("字符串常量") {
			System.out.println("method");
			try {
				while(true){
					System.out.println(Thread.currentThread().getName()+" start");
					Thread.sleep(1000);
					System.out.println(Thread.currentThread().getName()+" end");
					
				}
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
	
	/**
	 * @param args
	 */
	public static void main(String[] args) {

		final StringLock stringLock = new StringLock();
		Thread t1 = new Thread(new Runnable() {
			
			public void run() {
				stringLock.method();
			}
		},"t1");
		
		Thread t2 = new Thread(new Runnable() {
			
			public void run() {
				stringLock.method();
			}
		},"t2");
		t1.start();
		t2.start();
	}

}




六、不要试图改变锁

改变当前运行的锁,会造成锁的失效

package com.study.current.thread.day01;

/**
 * 不要修改锁对象
 * 会导致锁失效
 * 开始几个线程争夺 a 锁, 第一个线程 获取 a ,并把 锁改为 b ,第二个线程则无需等待 a 锁的释放,直接获取 b 锁,
 * 就不能起到锁的作用
 */
public class ChangeLock {

	private String lock = "abc";
	public void changeLock(){
		synchronized (lock) {
			System.out.println(Thread.currentThread().getName() + " start");
			try {
				lock = "bcd" ;
				Thread.sleep(2000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			System.out.println(Thread.currentThread().getName()+" end");
			
		}
	}
	
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		final ChangeLock lock = new ChangeLock();
		Thread t1 = new Thread(new Runnable() {
			
			public void run() {
				lock.changeLock();
			}
		},"t1");
		
		Thread t2 = new Thread(new Runnable() {
			
			public void run() {
				lock.changeLock();
			}
		},"t2");
		
		t1.start();
		t2.start();
	}

}




七、对象锁,其属性值得改变不影响锁的使用

锁对象的改变问题,当使用一个对象进行加锁的时候,要注意对象本身发生改变的时候,那么持有的锁就不同。
如果对象本身不发生改变,那么依然是同步的,即使是对象的属性发生了改变。

package com.study.current.thread.day01;

/**
 * 对象的属性值的变化,不影响锁的使用
 */
public class ModifyLock {

	private String name ;
	private String pass ;
	
	public synchronized void changeAttribute(String name,String pass){
		System.out.println(Thread.currentThread().getName() + " start");
		this.setName(name);
		this.setPass(pass);
		System.out.println(Thread.currentThread().getName() + " modify name:"+name+" pass:"+pass);
		try {
			Thread.sleep(2000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println(Thread.currentThread().getName() + " end");
	}
	
	
	
	
	public String getName() {
		return name;
	}


	public void setName(String name) {
		this.name = name;
	}


	public String getPass() {
		return pass;
	}


	public void setPass(String pass) {
		this.pass = pass;
	}


	/**
	 * @param args
	 */
	public static void main(String[] args) {
		final ModifyLock lock = new ModifyLock();
		Thread t1 = new Thread(new Runnable() {
			
			public void run() {
				lock.changeAttribute("zhangsan", "1111");
			}
		},"t1");
		
		Thread t2 = new Thread(new Runnable() {
			
			public void run() {
				lock.changeAttribute("lisi", "2222");
			}
		},"t2");
		
		t1.start();
		t2.start();
	}

}




分享到:
评论

相关推荐

    java_synchronized详解

    ### Java synchronized 关键字详解 #### 一、synchronized关键字简介 `synchronized`是Java语言提供的关键字之一,用于实现线程间的同步控制。通过在方法或代码块上使用`synchronized`,可以确保同一时间只有一个...

    java中synchronized用法

    "Java 中 synchronized 用法详解" Synchronized 是 Java 语言中用于解决多线程共享数据同步问题的关键字。它可以作为函数的修饰符,也可以作为函数内的语句,用于实现同步方法和同步语句块。在 Java 中,...

    java锁机制Synchronizedjava锁机制Synchronized

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

    java里面synchronized用法.doc

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

    Android synchronized 测试案例

    在Android开发中,`synchronized`关键字是Java语言中用于实现线程同步的重要工具,它在多线程环境下确保了共享资源的安全访问。本测试案例深入探讨了`synchronized`的使用方法,包括同步单个对象、同步多个对象以及...

    Java synchronized使用案例

    Java中的`synchronized`关键字是多线程编程中的一个重要概念,用于控制并发访问共享资源,以保证数据的一致性和完整性。这个关键词提供了互斥锁机制,防止多个线程同时执行同一段代码,确保了线程安全。 一、`...

    synchronized的几种示例

    在Java编程语言中,`synchronized`关键字是一个重要的并发控制机制,用于确保多线程环境下的数据一致性。本文将深入探讨`synchronized`的几种使用示例,包括方法加锁、代码块加锁(针对`this`和对象)以及静态方法...

    volatile和synchronized的区别

    ### volatile与synchronized的区别 #### 一、锁的特性:互斥与可见性 在并发编程中,锁作为实现线程安全的一种手段,其核心作用在于提供两种特性:互斥和可见性。 - **互斥**:互斥是指在任何时刻,只允许一个...

    synchronized用法大全实例

    在Java多线程编程中,`synchronized`关键字是一个至关重要的工具,用于实现线程间的同步,以确保共享资源的安全访问。本实例大全将全面解析`synchronized`的使用方式,包括同步方法、同步语句块、类锁和对象锁。 ##...

    synchronized并发讲解源码.zip

    在Java编程语言中,`synchronized`关键字是一个非常重要的并发控制机制,用于保证多线程环境下的数据一致性。本文将深入解析`synchronized`的工作原理、使用方式以及它在并发编程中的重要性。通过分析提供的源码,...

    java同步synchronized关键字用法示例

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

    synchronized关键字的用法详解

    ### synchronized关键字的深入解析 #### 一、synchronized关键字的重要性 `synchronized`关键字在Java语言中扮演着极其重要的角色,它是实现线程安全的核心手段之一。通过`synchronized`关键字,开发人员可以在多...

    synchronized关键字的实质及用法

    《深入理解Java中的synchronized关键字》 在Java编程语言中,`synchronized`关键字是用于实现线程同步的重要工具,它的本质在于确保多线程环境下的数据一致性与安全性。通过`synchronized`,我们可以控制对共享资源...

    Synchronized关键字的用法

    ### Synchronized关键字在Java中的应用 #### 概述 `synchronized`是Java语言中的一个关键字,主要用于实现线程同步,防止多个线程同时访问共享资源而导致的数据不一致问题。通过`synchronized`关键字,开发者可以...

    [JAVA][synchronized的使用]

    在Java编程语言中,`synchronized`关键字是一个至关重要的概念,它主要用于实现线程同步,以确保多线程环境下的数据一致性与安全性。本篇文章将深入探讨`synchronized`的使用,包括其基本原理、使用方式以及实际应用...

    Java synchronized详细解读.docx

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

    synchronized与单例的线程安全

    "synchronized"关键字和单例模式是确保线程安全的两种常见手段。本文将详细探讨这两个概念及其在实现线程安全中的作用。 一、synchronized关键字 synchronized是Java中的一个关键同步机制,用于控制对类或对象的...

    生产者消费者Java—synchronized 机制

    在这个项目中,开发者利用`synchronized`关键字来实现线程同步,确保数据在生产与消费过程中的安全。 `synchronized`是Java中用于实现线程互斥的关键字,它提供了对共享资源的独占访问。当一个线程进入由`...

    第15讲 synchronized和ReentrantLock有什么区别呢?1

    在Java编程中,synchronized和ReentrantLock都是用于实现线程同步的重要工具,它们在并发控制方面扮演着关键角色。然而,两者之间存在一些显著的区别,这些差异体现在功能、灵活性、性能以及使用场景上。 首先,...

Global site tag (gtag.js) - Google Analytics