`
yuyiming1986
  • 浏览: 63426 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论
阅读更多
Java线程新的同步机制

1.可重入锁ReentrantLock,相当于synchronized块,为临界区提供互斥访问机制.

  (1).相关的接口

  创建一个可重入锁
  Lock lock = new ReentrantLock();

  请求锁,如果锁被当前另一个线程持有,则阻塞。
  void lock() 

  释放锁
  void unlock();

  非阻塞型lock()
  boolean tryLock();


  (2).使用基本结构
   locker.lock();

   try{

     //code here to access the cirtical section
   }finally{
locker.unlock();
   }

   这种结构保证在任何时刻只有一个线程能够进入临界区,如果一个线程锁住了锁对象,其他任何线程在调用lock时,都会被阻塞,直到第一个线程释放锁对象。而且无论try块是否抛出异常,都会执行finally block,解锁locker.

  (3).锁的可重入性:锁是可重入的,线程能够重复地获取它已经拥有的锁。锁对象维护一个持有计数(hold count)来追踪对lock方法的嵌套调用。线程在每次调用lock后都要调用unlock来释放锁。由于这个特性,被一个锁保护的代码可以调用另一个使用相同锁的方法。

  (4).示例代码:

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

class WorkerOne extends Thread{
	
	private Lock locker;
	
	public WorkerOne (Lock locker){
		this.locker = locker;
	}
	
	public void run(){
		
		locker.lock();
		
		try{
			System.out.println(Thread.currentThread().getName()+":step into critical section");
		}finally{
			locker.unlock();	
		}
	}
}


class WorkerTwo extends Thread{
	
	private Lock locker;
	
	public WorkerTwo (Lock locker){
		this.locker = locker;
	}
	
	public void sayHello(){
		
		locker.lock();
		
		try{
			System.out.println(Thread.currentThread().getName()+":call sayHello()");
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}finally{
			
			locker.unlock();
		}
	}
	
	public void run(){
		
		locker.lock();
			
		try{
			System.out.println(Thread.currentThread().getName()+":setp into critical section");
                        //测试锁的可重入性 
			sayHello();
		}finally{
			locker.unlock();	
		}
	}
}


public class Test5 {

	public static void main(String[] args) {
		
		Lock locker = new ReentrantLock();
		
		WorkerOne wo= new WorkerOne(locker);
		wo.setName("WorkerOne");
		
		WorkerTwo wt = new WorkerTwo(locker);
		wt.setName("WorkerTwo");
		
		wt.start();
		wo.start();	
	}
}


输出:
WorkerTwo:setp into critical section
WorkerTwo:call sayHello()
WorkerOne:step into critical section


2.条件对象Condition,相当于wait-notify机制,提供一种线程间的等待通知机制,condition中的等待-通知方法是await(),signal

(),signalAll(),也需要在互斥环境下被调用。

(1)相关的接口

  创建Condition对象,Condition对象是跟Lock关联在一起的.
  Lock locker = new ReentrantLock();
  Condition cond = locker.newCondition();

  把此线程放到条件的等待集中。
  void await();

  解除此条件的等待集中所有线程的阻塞状态
  void signalAll();

  在此条件的等待集中随机选择一个线程,解除其阻塞状态。
  void signal();


(2).使用的基本结构
 
   //初始时ok_to_proceed为false.
   locker.lock()
    
   try{
        while(!ok_to_proceed){
   //进入等待此条件集中,被阻塞,它维持状态直到另一个线程调用同一个条件上的
   //signalAll/signal方法时为止。
          cond.await();
        }
   }finally{
	locker.unlock();
   }


  
locker.lock();
   try{
      //调用将解除所有等待此条件下的线程的阻塞状态。当线程从等待集中被移走时,它们将再次成为可运行的,调度器将再次激活它们    
      //此时,它们将试图重新进入对象。一旦锁可获得,它们中的某个线程将从await调用返回,从而获得锁并从它被阻塞的地方继续执行。
      ok_to_proceed = true;
      cond.signalAll() or cond.signal();
      
   }finally{
       locker.unlock();
   }


   ok_to_proceed也是为了防止wait-notify出现的问题,即再wait之间,notify()已经给出通知,此时wait只会一直等待下去,这样就保证了signal()线程的通知被await()线程接收到。


(3)测试代码:
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

class GlobalV{
	
	public final static Lock locker = new ReentrantLock();
	public final static Condition cond = locker.newCondition();
	public static boolean to_proceed = false;
}

class Response extends Thread{
	
	public void run(){
		
		while(true){
			
			GlobalV.locker.lock();
		
			try{
				
				while(!GlobalV.to_proceed){
					GlobalV.cond.await();
				}
				
				System.out.println("Response:finish a job");
				GlobalV.to_proceed = false;
				
			}catch(Exception e){
				e.printStackTrace();
			}finally{
				GlobalV.locker.unlock();
			}	
		}
	}
}


class Request extends Thread{

	public void run(){
	
		while(true){
			
			GlobalV.locker.lock();
		
			try{
				
				GlobalV.to_proceed = true;
				GlobalV.cond.signalAll();
				System.out.println("Request:send a job to Response");
				
			}finally{
				GlobalV.locker.unlock();
			}
			
			
			try {
				Thread.sleep(2000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			
			
		}
	}
}


public class Test6 {

	public static void main(String[] args) {
		
		Request req = new Request();
		Response res = new Response();
		
		req.start();
		res.start();
	}
}


输出:
Request:send a job to Response
Response:finish a job
Request:send a job to Response
Response:finish a job
Request:send a job to Response
Response:finish a job
Request:send a job to Response
Response:finish a job


3.读写锁ReentrantReadWriteLock,适用于"读多写少"的多线程应用场景,"读-写"互斥,"写-写"互斥,而读-读可以共享同读锁,即一个线程获取读锁,其它线程可直接进入读,不会被阻塞。


  (1).相关接口

    创建读写锁对象
    ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();

    获取读锁
    Lock readLock = rwLock.readLock();

    获取写锁
    Lock writeLock = rwLock.writeLock();


  (2).读写锁使用基本结构
 
   //对所有的读操作添加读锁
  readLock.lock();

   try{
     //code to read 
  
   }finally{
	readLock.unlock();
   }

 
   //对所有的写操作添加写锁

   writeLock.lock();
    try{

	//code to write
    }finally{
   	writeLock.unlock();
    }



  (3).测试代码:
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

class Reader extends Thread {

	private Lock readLock = null;

	public Reader(Lock readLock) {
		this.readLock = readLock;
	}

	public void run() {

		while (true) {
			readLock.lock();

			try {
				System.out.println(Thread.currentThread().getName()
						+ ":read action for 1 seconds-"+ReadWriteLock.testVal);
				
			} finally {
				readLock.unlock();
			}

			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
}

class Writer extends Thread {

	private Lock writeLock = null;

	public Writer(Lock writeLock) {
		this.writeLock = writeLock;
	}

	public void run() {

		while (true) {
			writeLock.lock();

			try {

				System.out.println(Thread.currentThread().getName()
						+ ":write action for 2 seconds");
				
				if(ReadWriteLock.testVal.equals("1111"))
					ReadWriteLock.testVal = "2222";
				else
					ReadWriteLock.testVal = "1111";

			} finally {
				writeLock.unlock();
			}

			try {
				Thread.sleep(2000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}

}

public class ReadWriteLock {

	public static String  testVal = "Initiation";
	
	public static void main(String[] args) {

		ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
		Lock readLock = lock.readLock();
		Lock writeLock = lock.writeLock();
		

		Reader reader1 = new Reader(readLock);
		reader1.setName("reader1");

		Reader reader2 = new Reader(readLock);
		reader2.setName("reader2");

		Reader reader3 = new Reader(readLock);
		reader3.setName("reader3");

		Reader reader4 = new Reader(readLock);
		reader4.setName("reader4");

		Writer writer = new Writer(writeLock);
		writer.setName("writer1");

		reader1.start();
		reader2.start();
		reader3.start();
		reader4.start();

		writer.start();
	}

}


输出:
reader1:read action for 1 seconds-Initiation
reader3:read action for 1 seconds-Initiation
writer1:write action for 2 seconds
reader2:read action for 1 seconds-1111
reader4:read action for 1 seconds-1111
reader3:read action for 1 seconds-1111
reader1:read action for 1 seconds-1111
reader4:read action for 1 seconds-1111
reader2:read action for 1 seconds-1111
writer1:write action for 2 seconds
reader4:read action for 1 seconds-2222
reader1:read action for 1 seconds-2222
reader3:read action for 1 seconds-2222
reader2:read action for 1 seconds-2222


4.总结

(1).Lock接口替代synchronized
     Lock接口可以比sychronized提供更广泛的锁定操作.可以提供多把不同的锁.且锁之间互不干涉.
     Lock接口提供lock()与unlock()方法, 使用明确调用来完成同步的, OO思想好于前者.
     Lock可以自由操控同步范围(scope).
     Lock接口支持nested lock(嵌套锁定).并提供了丰富的api.
     Lock接口提供了tryLock()方法, 支持尝试取得某个object lock.


 



分享到:
评论

相关推荐

    Java多线程同步机制研究分析.pdf

    Java多线程同步机制研究分析 Java多线程同步机制是Java编程语言中的一种机制,它允许多个线程同时执行,提高了系统资源的利用率和安全性。但是,多线程中最重要的问题是线程的同步和共享资源的访问保护。本文通过对...

    Java多线程同步机制的应用分析.pdf

    "Java多线程同步机制的应用分析" Java多线程同步机制的应用分析是指在Java语言中,如何使用同步机制来保护临界区,以避免多线程之间的冲突和错误。该机制通过管程机制和同步语法来保护临界区,使得多线程可以安全...

    java的线程同步机制synchronized关键字的理解_.docx

    Java 线程同步机制中 synchronized 关键字的理解 Java 的线程同步机制是为了解决多个线程共享同一片存储空间所带来的访问冲突问题。其中,synchronized 关键字是 Java 语言中解决这种冲突的重要机制。 ...

    Java多线程同步.pdf

    "Java多线程同步.pdf" Java多线程同步是指在Java语言中,如何使用synchronized关键字和其他同步机制来确保多线程程序的正确执行。...Java多线程同步机制是Java语言中的一种重要机制,用于确保多线程程序的正确执行。

    java 线程同步 信号量控制同步

    线程同步机制是 Java 编程中的一种重要机制,用于控制多个线程之间的资源访问顺序,以避免线程之间的冲突和数据不一致。开发者需要牢牢记住线程同步的四点要素,即线程同步就是线程排队,共享资源需要同步,变量需要...

    Java多线程同步机制在售票系统的实现

    ### Java多线程同步机制在售票系统的实现 #### 一、引言 随着计算机硬件的发展,多核处理器已经成为主流配置,这为多线程编程提供了更广阔的应用场景。多线程能够充分利用多核处理器的优势,提高程序的并发性和...

    JAVA 线程实现数据库的主从同步更新

    Java线程提供了异常处理机制,可以使用try-catch-finally块来捕获和处理异常。如果同步失败,可能需要回滚主数据库的事务,或者标记异常并尝试在后续同步周期中再次处理。 5. **性能优化**: 为提高同步效率,可以...

    Java多线程-线程的安全问题与线程的同步机制介绍

    常见的线程同步机制有:同步块(Synchronized Block)、同步方法(Synchronized Method)、锁(Lock)、Atomic 变量等。 四、线程安全问题解决方案 (1)方式一:实现Runnable接口 可以通过实现Runnable接口来...

    基于Java多线程同步的安全性研究.pdf

    文章首先介绍了Java多线程同步的必要性和重要性,然后讨论了Java多线程同步机制的实现方法,包括使用synchronized关键字和Java.util.concurrent.locks包中的Lock对象。接着,文章讨论了Java多线程同步机制中可能出现...

    Java多线程-同步机制解决线程安全问题方式一:同步代码块

    为了解决这个问题,Java提供了同步机制,其中一种常用的方式就是同步代码块(synchronized block)。 一、同步机制介绍 同步机制的核心在于控制对共享资源的访问,确保在同一时刻只有一个线程能够执行特定的代码...

    java线程线程安全同步线程

    总的来说,理解和掌握Java线程的创建、状态管理、同步机制和线程安全是进行多线程编程的基础,这对于开发高效、稳定的并发程序至关重要。在实际编程中,应充分利用Java提供的工具和机制,避免潜在的并发问题,提升...

    JAVA多线程同步机制及其应用.doc

    Java多线程同步机制及其应用是Java编程中至关重要的一环,尤其在开发高并发、高性能的应用程序时,理解并掌握这些机制是必不可少的。本文档详细介绍了Java中多线程的相关概念、创建方式、线程管理、同步机制以及一个...

    Java多线程-同步机制解决线程安全问题方式二:同步方法

    为了确保并发执行的线程能够正确地处理这些共享资源,Java提供了多种同步机制,其中之一就是同步方法。同步方法通过在方法前加上`synchronized`关键字来实现,确保同一时间只有一个线程可以执行该方法。 一、同步...

    Java多线程同步机制在网络售票系统中的应用.zip

    Java多线程同步机制在网络售票系统中的应用是一个关键的话题,特别是在高并发环境下,如网络售票系统,正确地处理多线程同步是确保数据一致性、避免资源竞争和死锁的重要手段。下面将详细介绍Java多线程同步机制以及...

    去故新 Java线程新同步机制

    1、可重入锁ReentrantLock,相当于synchronized块,为临界区提供互斥访问机制。 (1) 相关的接口 创建一个可重入锁 Lock lock = new ReentrantLock(); 请求锁,如果锁被当前另一个线程持有,则阻塞。 void ...

    Java线程及同步(synchronized)样例代码

    通过具体的代码实现,我们将深入理解Java中的线程同步机制,并学习如何在实际编程中正确地使用这些机制。 #### 二、核心概念与原理 ##### 1. Java线程基础 Java中的线程是程序执行的基本单位,每个线程有自己的...

    JAVA实现线程间同步与互斥生产者消费者问题

    在`JThreadSynch`这个压缩包文件中,我们可以预见到包含的Java源代码将展示以上的一种或多种机制,通过具体的示例代码来解释和实现生产者消费者问题的线程同步和互斥。通过学习和理解这个示例,开发者可以更好地掌握...

    java多线程同步问题

    多线程注意:wait()方法的调用要有判定条件常用 while () obj.wait(timeout, nanos); ... // Perform action appropriate to condition } synchronized会影响共享数据,但对其他语句的执行不会有规律了!

Global site tag (gtag.js) - Google Analytics