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

Java Concurrency: Thread&Locks

阅读更多

Synchronized & ReentrantLock

 

1) Basic Thread Operations

    1) void notifyAll()

        1> unblocks the threads that called wait on this object.

        2> This method can only be called from within a synchronized method or block.

        3> This method throws an IllegalMonitorStateException if the current thread is not the owner of the object's lock.

    2) void notify()

        1> Unblocks one randomly selected thread among the threads that called wait on this object.

        2> This method can only be called from within a synchronized method or block.

        3> The method throws an IllegalMonitorStateException if the current thread is not the owner of the object's lock.

    3) void wait(long millis)

        void wait(long millis, int nanos)

        1> Cause a thread to wait until it is notified or until the specified amount of time has passed.

        2> These methods can only be called from within a synchronized method.

        3> They throw an IllegalMonitorStateException if the current thread is not the owner of the object's lock.

    Demo for Producer&Consumer using wait()&notify()

package edu.xmu.thread;

import java.util.ArrayList;
import java.util.List;

public class NotifyTest {
    public static void main(String[] args) {
	List<String> data = new ArrayList<String>();
	Thread consumer = new Thread(new DataConsumer(data));

	Thread producer = new Thread(new DataProducer(data));
	Thread producer2 = new Thread(new DataProducer(data));
	Thread producer3 = new Thread(new DataProducer(data));

	producer.start();
	producer2.start();
	producer3.start();

	consumer.start();
    }
}

class DataConsumer implements Runnable {
    List<String> data;

    public DataConsumer(List<String> data) {
	super();
	this.data = data;
    }

    @Override
    public void run() {
	try {

	    while (true) {
		Thread.sleep((long) (1000 * Math.random()));
		synchronized (data) {
		    System.out.println(String.format(
			    "Thread: [%s] attempts to consume data",
			    Thread.currentThread()));

		    while (data.size() == 0) {
			System.out.println(String.format(
				"Thread: [%s] is waiting for consuming data",
				Thread.currentThread()));
			data.wait();
		    }

		    String value = data.remove(0);

		    System.out.println(String.format(
			    "Thread: [%s] consumed data: [%s]",
			    Thread.currentThread(), value));

		    data.notifyAll(); // notifyAll to wake up all waitting threads, especially producer thread, to check while(boolean) and attempt acquire locks for data again.
		}
	    }

	} catch (Exception e) {
	    e.printStackTrace();
	}

    }
}

class DataProducer implements Runnable {
    List<String> data;

    public DataProducer(List<String> data) {
	super();
	this.data = data;
    }

    @Override
    public void run() {
	try {
	    while (true) {
		Thread.sleep((long) (1000 * Math.random()));
		synchronized (data) {
		    System.out.println(String.format(
			    "Thread: [%s] attempts to produce data",
			    Thread.currentThread()));

		    while (data.size() == 10) {
			System.out.println(String.format(
				"Thread: [%s] is waiting for producing data",
				Thread.currentThread()));
			data.wait();
		    }
		    String value = String.valueOf(100 * Math.random());
		    data.add(value);

		    System.out.println(String.format(
			    "Thread: [%s] produced data: [%s]",
			    Thread.currentThread(), value));

		    data.notifyAll(); // notifyAll to wake up all waitting threads, especially consumer threads, to check while(boolean) and attempt to acquire lock for data again.
		}
	    }
	} catch (Exception e) {
	    e.printStackTrace();
	}
    }

}

 

2) A quick review of synchronized

        Delcaring a block of code to be synchronized has two important consequences

            1> Atomicity: Means that only one thread at a time can execute code protected by a given monitor object(lock).

                                 Allowing you to prevent multiple threads from colliding with each other when updating shared state.

            2> Visibility:   Visibility is more subtle. It deals with the vagaries of memory caching and compiler optimizations.

                                 Ordinarily, threads are free to cache values for variables in such a way that they are not necessarily immediately visible to other threads

                                 (whether it be in registers, in processor-specific caches, or through instruction reordering or other compiler optimizations).

                                  But if the developer has used synchronization, the runtime will ensure that updates to variables made by one thread prior to exiting a synchronized block will become immediately visible to another thread when it enters a aynchronized block protected by that same monitor(lock).

        So synchronization takes care of everything needed to reliably update multiple shared variables without race conditions or corrupting data(provideded the synchronization boundaries are in the right place). and ensures that other threads that properly synchronized will see the most update-to-date values of those variables.

        "Whenever you will be writing a variable that may next be read by another thread, or reading a variable that may have last been written by another thread, you must synchronize."

 

3) Limitations of synchronized

    Synzhronization is good, but not perfect. It has some functional limitations.

        1) It is not possible to interrupt a thread that is waiting to acquire a lock.

        2) It is not possible to poll for a lock or attempt to acquire a lock without being willing to wait forever for it.

        3) It requires that locks be released in the same stack frame in which they were acquired.<?>

    Apart of above limitations, it behaves just like ReentrantLock which is reentrantable.

 

4) ReentrantLock

    1) What is reentrant?

            Simply that there is an acquisition count associated with the lock, and if a thread that holds the lock acquires it again, the acquisition count is incremented ant the lock then needs to be released twice to truly release the lock.

        Below is an example of UnReentrantLock:

package edu.xmu.thread;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class LockTest {
    public static void main(String[] args) {
	ExecutorService pool = Executors.newCachedThreadPool();

	Counter counter = new Counter();
	List<Runnable> taskList = initTaskList(counter);

	for (Runnable task : taskList) {
	    pool.submit(task);
	}

	pool.shutdown();
    }

    private static List<Runnable> initTaskList(final Counter counter) {
	List<Runnable> taskList = new ArrayList<Runnable>();

	for (int i = 0; i < 5; i++) {
	    taskList.add(new Runnable() {
		@Override
		public void run() {
		    try {
			counter.increase();
		    } catch (InterruptedException e) {
			e.printStackTrace();
		    }
		}
	    });
	}
	return taskList;
    }

    private static class Counter {
	private UnReentrantLock lock = new UnReentrantLock();
	private int count = 0;

	public void increase() throws InterruptedException {
	    lock.lock();
	    count++;

	    try {
		Thread.sleep((long) (Math.random() * 100 + 1));
	    } catch (InterruptedException e) {
		e.printStackTrace();
	    }

	    System.out.println("CurrentThread: [" + Thread.currentThread()
		    + "]. Count = " + count);

	    increase(); // Here we are trying to reentrant

	    lock.unlock();
	}
    }

    private static class UnReentrantLock {
	private boolean isLocked = false;

	public synchronized void lock() throws InterruptedException {
	    while (isLocked) {
		System.out.println(Thread.currentThread() + " is waiting");
		wait();
	    }
	    System.out.println(Thread.currentThread() + " got the lock");
	    isLocked = true;
	}

	public synchronized void unlock() {
	    isLocked = false;
	    notify();
	}
    }
}

        Output:

Thread[pool-1-thread-1,5,main] got the lock
Thread[pool-1-thread-2,5,main] is waiting
Thread[pool-1-thread-4,5,main] is waiting
Thread[pool-1-thread-5,5,main] is waiting
Thread[pool-1-thread-3,5,main] is waiting
CurrentThread: [Thread[pool-1-thread-1,5,main]]. Count = 1
Thread[pool-1-thread-1,5,main] is waiting

// Here we got deadlock. Thread-1 never released the lock and are trying to get the same lock.

         Below is an example of ReentrantLock:

package edu.xmu.thread;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class LockTest {
    public static void main(String[] args) {
	ExecutorService pool = Executors.newCachedThreadPool();

	Counter counter = new Counter();
	List<Runnable> taskList = initTaskList(counter);

	for (Runnable task : taskList) {
	    pool.submit(task);
	}

	pool.shutdown();
    }

    private static List<Runnable> initTaskList(final Counter counter) {
	List<Runnable> taskList = new ArrayList<Runnable>();

	for (int i = 0; i < 5; i++) {
	    taskList.add(new Runnable() {
		@Override
		public void run() {
		    try {
			counter.increase();
		    } catch (InterruptedException e) {
			e.printStackTrace();
		    }
		}
	    });
	}
	return taskList;
    }

    private static class Counter {
	private int count = 0;

	public void increase() throws InterruptedException {
	    synchronized (this) {
		count++;

		try {
		    Thread.sleep((long) (Math.random() * 100 + 1));
		} catch (InterruptedException e) {
		    e.printStackTrace();
		}

		System.out.println("CurrentThread: [" + Thread.currentThread()
			+ "]. Count = " + count);

		increase(); // Here we are trying to reentrant
	    }
	}
    }
}

        Output:

CurrentThread: [Thread[pool-1-thread-1,5,main]]. Count = 1
CurrentThread: [Thread[pool-1-thread-1,5,main]]. Count = 2
CurrentThread: [Thread[pool-1-thread-1,5,main]]. Count = 3
CurrentThread: [Thread[pool-1-thread-1,5,main]]. Count = 4
CurrentThread: [Thread[pool-1-thread-1,5,main]]. Count = 5
CurrentThread: [Thread[pool-1-thread-1,5,main]]. Count = 6
CurrentThread: [Thread[pool-1-thread-1,5,main]]. Count = 7
CurrentThread: [Thread[pool-1-thread-1,5,main]]. Count = 8
...

// Before thread-1 release the lock, it can still get the same lock.
// That is the meaning of re-entrant.

        Or we can replace "synchronized{}" with code below:

    private static class Counter {
	private Lock lock = new ReentrantLock();
	private int count = 0;

	public void increase() throws InterruptedException {
	    lock.lock();
	    count++;

	    try {
		Thread.sleep((long) (Math.random() * 100 + 1));
	    } catch (InterruptedException e) {
		e.printStackTrace();
	    }

	    System.out.println("CurrentThread: [" + Thread.currentThread()
		    + "]. Count = " + count);

	    increase(); // Here we are trying to reentrant

	    lock.unlock();
	}
    }

 

    2) The Lock framework in java.util.concurrent.lock is an abstraction for locking, allowing for lock implementations that are implemented as Java classes rather than as a language characteristics.

        It makes room for multiple implementations of Lock, which may have different scheduling algorithms, performance characteristics, or locking semantics.

 

Reference Links:
    1) http://www.ibm.com/developerworks/java/library/j-jtp10264/

分享到:
评论

相关推荐

    concurrency:Java Concurrency in Practice源代码-java source code

    《Java并发编程实践》(Java Concurrency in Practice)是一本深度探讨Java多线程和并发编程的经典著作。这本书由Brian Goetz、Tim Peierls、Joshua Bloch、David Holmes和Doug Lea合著,旨在帮助Java开发者理解和解决...

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

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

    Java 7 Concurrency Cookbook

    useful mechanisms included in Version 7 of the Java concurrency API, so you will be able to use them directly in your applications, which are as follows: f f t e n . d u o l Basic thread management w....

    Concurrency:Java多线程学习

    避免死锁的方法包括避免嵌套锁、使用定时锁(如`java.util.concurrent.locks.Lock`)和避免持有多个锁。 3. **线程通信**:Java提供了`wait()`, `notify()`和`notifyAll()`方法来实现线程间的通信。这些方法必须在`...

    《Java Concurrency in Practice》代码示例

    《Java Concurrency in Practice》是Java并发编程领域的一本经典著作,由Brian Goetz、Tim Peierls、Joshua Bloch、David Holmes和Doug Lea合著。这本书深入浅出地探讨了Java平台上的多线程和并发编程,提供了丰富的...

    Java 7 Concurrency Cookbook EN pdf及代码

    《Java 7 Concurrency Cookbook》是一本专注于Java并发编程实践的书籍,主要针对Java 7版本。这本书旨在帮助开发者在多线程环境下更好地理解和解决性能和正确性问题。以下是本书中涉及的一些关键知识点: 1. **Java...

    java-concurrency:Java 并发习惯用法的一些示例

    - Java中的线程是通过`Thread`类或实现`Runnable`接口创建的。线程安全是指在多线程环境下,一个方法或类可以正确地处理多个线程的访问,避免数据不一致或竞态条件。 2. **同步机制** - **synchronized**关键字...

    Android代码-java-concurrency-patterns

    Java Concurrency Patterns and Features Concurrency Patterns and features found in Java, through multithreaded programming. Features: Threads and Runnables Locks Intrinsic Explicit Reentrant Read...

    java concurrency in practice.rar

    - 如何检测和避免这些并发问题,如Java的`java.util.concurrent.locks.Condition`的`await()`和`signal()`方法。 7. **并发性能优化** - **线程池的配置与调整**:合理设置核心线程数、最大线程数、队列容量等...

    Core Java Concurrency

    ### Core Java Concurrency #### 知识点概览 1. **Java Memory Model(Java内存模型)** 2. **Monitor(监视器)** 3. **Atomic Field Assignment(原子字段赋值)** 4. **Thread(线程)** 5. **synchronized...

    Advanced-Concurrency:尝试并发多线程程序

    3. **java.util.concurrent.locks** 包中的锁接口和类:如ReentrantLock、Condition等,提供了更灵活的锁机制和等待/通知机制。 4. **java.util.concurrent.CyclicBarrier** 和 **java.util.concurrent....

    core java concurrency

    Java通过java.lang.Thread类提供了对线程的支持。Java虚拟机为每个线程分配一定的栈空间,并通过线程调度器进行线程的调度。程序员可以使用Thread类来创建线程,并通过run()方法来定义线程的行为。 五、java.util....

    Java.Concurrency.in.Practice.pdf

    本文档为《Java并发编程实践》(Java Concurrency in Practice)的电子版PDF文件,这本书由Brain Goetz、Tim Peierls、Joshua Bloch、Joseph Bowbeer、David Holmes以及Doug Lea所著。该书详细探讨了Java语言中的...

    Concurrency学习源码.zip

    Java的`java.util.concurrent.ThreadPoolExecutor`和C++的`std::thread::hardware_concurrency()`都是线程池的实现。 7. **并发容器**:为支持并发访问,一些高级编程语言提供了线程安全的容器,如Java的`java.util...

    Java - The Well-Grounded Java Developer

    - **Overview**: Explores modern concurrency patterns and APIs available in Java, focusing on efficient parallel processing and thread safety. - **Key Concepts**: - **Java Memory Model (JMM)**: ...

    java并发编程技术

    4. **并发包JUC(Java Util Concurrency)**:JUC是Java提供的高级并发工具包,包含如Semaphore(信号量)、CountDownLatch(计数器)、CyclicBarrier(回环栅栏)、Exchanger(交换器)等工具类,它们简化了多线程...

    Java7ConcurrencyCookbook_unit2

    《Java 7 Concurrency Cookbook_unit2》是针对Java并发编程领域的一份宝贵资源,它包含了大量关于如何在Java 7环境中高效、安全地编写多线程程序的实例和最佳实践。这个单元,"unit2thread",很可能聚焦于线程管理和...

    Java核心技术1英文版

    根据提供的文件信息,“Java核心技术I英文版第九版本”是一本详细介绍Java编程语言核心概念与实践应用的专业书籍。本书由Cay S. Horstmann和Gary Cornell共同编写,并由Pearson出版社出版。以下是从该书标题、描述...

Global site tag (gtag.js) - Google Analytics