Multi-Programming-12 Semaphore信号量机制

1.Semaphore 和 ReentrantLock 的condition有什么不同(acquire()/release()、await()/signal())?

这里有关于此问题的详尽问答,下面贴下截图。



大意:java.util.concurrent.Semaphore是相对高级的同步机制,一般用来限制并发访问同一资源的线程数量,通过每个线程访问资源之前调用acquire()方法,这样会使permits数量-1.访问结束之后调用release()方法,这样会使permits数量+1.
java.util.concurrent.locks.Condition是相对来说低级别的同步机制,可以看作增强版本的java.lang.Object notify() and wait()。

2.Semaphore 和 ReentrantLock不同?

这里有关于该问题的问答。

3.  Semaphore 和 mutex 有什么区别?

可以点击 此处获得关于semaphore & mutex的详细讨论内容,下面是对于该问题的总结。
主要有以下两点区别:
1). 所谓的ownership 关系上,对于信号量semaphore而言,是没有ownership这种说法的,即:在使用semaphore时,一个线程可以在没有acquire的情形下release该资源所对应的信号量; 但对于mutex则不然,只能释放所获取到的锁。

Releases a permit, returning it to the semaphore.

Releases a permit, increasing the number of available permits by one. If any threads are trying to acquire a permit, then one is selected and given the permit that was just released. That thread is (re)enabled for thread scheduling purposes.

There is no requirement that a thread that releases a permit must have acquired that permit by calling acquire. Correct usage of a semaphore is established by programming convention in the application.
2). 一句话:Semaphore信号量机制限制了访问一个共享资源的线程的最大数量!而MUTEX则只允许共享资源在一个时刻只能被一个线程所访问。



4.信号量Demo和结果

1. 同时最多10个线程访问的实例:这里设置Semaphore大小为10, 同时10个线程访问共享对象。
package com.fqy.mix;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;

public class SemaphoreDemo {
	public static void main(String[] args) {
		SemaphoreDemoUtil.demonstrate();
	}

}

class SemaphoreDemoUtil {
	public static void demonstrate() {
		Long startTime = System.currentTimeMillis();
		//The Connection instance is not created by multiple threads, so no concurrent issue about this static method. 
		Connection connection = Connection.getInstance();
		ExecutorService executor = Executors.newCachedThreadPool();
		for (int i = 0; i < 30; i++) {
			executor.submit(new Runnable() {

				@Override
				public void run() {
					try {
						connection.doConnect();
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
			});
		}
		executor.shutdown();
		try {
			executor.awaitTermination(1, TimeUnit.MINUTES);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		Long endTime = System.currentTimeMillis();
		System.out.println("Total taken time is: " + (endTime - startTime));
	}
}

class Connection {
	private int count = 0;
	private Semaphore semaphore = new Semaphore(10);

	private Connection() {

	}

	private static final Connection INSTANCE = new Connection();

	public static Connection getInstance() {
		return INSTANCE;
	}

	private void connect() {
		synchronized (this) {
			count++;
			System.out.println("Current connections is: " + count);
		}
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		synchronized (this) {
			count--;
		}
	}

	public void doConnect() throws InterruptedException {
		try {
			semaphore.acquire();
			connect();
		} finally {
			semaphore.release();
		}

	}
}

运行结果:
Current connections is: 1
Current connections is: 2
Current connections is: 3
Current connections is: 4
Current connections is: 5
Current connections is: 6
Current connections is: 7
Current connections is: 8
Current connections is: 9
Current connections is: 10
Current connections is: 1
Current connections is: 2
Current connections is: 3
Current connections is: 4
Current connections is: 5
Current connections is: 6
Current connections is: 7
Current connections is: 8
Current connections is: 9
Current connections is: 10
Current connections is: 1
Current connections is: 2
Current connections is: 3
Current connections is: 4
Current connections is: 5
Current connections is: 6
Current connections is: 7
Current connections is: 8
Current connections is: 9
Current connections is: 10
Total taken time is: 3013

2. 这里模拟的是用户从图书馆借书的逻辑,图书馆最大书目为Semaphore的size,即:最多访问图书馆的线程数量为图书馆书目的大小。每次借出一本书则semaphore的availablePermits减1, 每次还一本书则semaphore的availablePermits加1. 每个线程在执行之前必须获得信号量通过acquire(),如果没有可用的permits则阻塞,线程在执行完成之后通过release()释放信号量。
package com.fqyuan._7semaphore;

public class Book {
	private String bookName;

	public Book(String name) {
		bookName = name;
	}

	public String getBookName() {
		return bookName;
	}

	public void read() {
		System.out.println(bookName + " is being read...");
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}
package com.fqyuan._7semaphore;

import java.util.concurrent.Semaphore;

public class Library {
	private static final int MAX_PERMIT = 3;
	private Semaphore availableBooks = new Semaphore(MAX_PERMIT, true);
	private Book[] books = { new Book("Art of war"), new Book("Tolerance"), new Book("Story of the mankind") };
	private boolean[] beingRead = new boolean[MAX_PERMIT];

	public Book issueBook() throws InterruptedException {
		availableBooks.acquire();
		// If upper code not blocked, we can always get an non-null book here
		return getNextAvailableBook();
	}

	private synchronized Book getNextAvailableBook() {
		Book result = null;
		for (int i = 0; i < MAX_PERMIT; i++) {
			if (beingRead[i] == false) {
				beingRead[i] = true;
				result = books[i];
				System.out.println(books[i].getBookName() + " is being issued...");
				break;
			}
		}
		return result;
	}

	public void returnBook(Book book) {
		if (markAsAvailableBook(book))
			availableBooks.release();
	}

	private synchronized boolean markAsAvailableBook(Book book) {
		boolean flag = false;
		for (int i = 0; i < MAX_PERMIT; i++) {
			if (book == books[i]) {
				if (beingRead[i] == true) {
					beingRead[i] = false;
					flag = true;
					System.out.println(book.getBookName() + " is returned...");
				}
			}
		}
		return flag;
	}
}

package com.fqyuan._7semaphore;

public class Reader implements Runnable {
	private Library library;

	public Reader(Library library) {
		this.library = library;
	}

	@Override
	public void run() {
		try {
			Book book = library.issueBook();
			book.read();
			library.returnBook(book);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

}

package com.fqyuan._7semaphore;

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

public class Main {
	public static void main(String[] args) {
		final int threadCnt = 6;
		final ExecutorService executor = Executors.newFixedThreadPool(threadCnt);
		final Library myLibrary = new Library();
		for (int i = 0; i < threadCnt; i++) {
			Reader reader = new Reader(myLibrary);
			executor.execute(reader);
		}
		executor.shutdown();
	}
}
//Running result:
Art of war is being issued...
Art of war is being read...
Tolerance is being issued...
Tolerance is being read...
Story of the mankind is being issued...
Story of the mankind is being read...
Art of war is returned...
Tolerance is returned...
Art of war is being issued...
Art of war is being read...
Story of the mankind is returned...
Tolerance is being issued...
Tolerance is being read...
Story of the mankind is being issued...
Story of the mankind is being read...
Art of war is returned...
Story of the mankind is returned...
Tolerance is returned...


4.己见

Semaphore机制是限制访问同一资源线程数量的,是一种更高级别的机制,可以和ReentrantLock等配合使用。
这里可以获取相关笔记和代码。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值