GP Coder

Trang chia sẻ kiến thức lập trình Java

  • Java Core
    • Basic Java
    • OOP
    • Exception Handling
    • Multi-Thread
    • Java I/O
    • Networking
    • Reflection
    • Collection
    • Java 8
  • Design pattern
    • Creational Pattern
    • Structuaral Pattern
    • Behavior Pattern
  • Web Service
    • SOAP
    • REST
  • JPA
  • Java library
    • Report
    • Json
    • Unit Test
  • Message Queue
    • ActiveMQ
    • RabbitMQ
  • All
Trang chủ Java Core Multi-Thread Semaphore trong Java

Semaphore trong Java

Đăng vào 18/09/2019 . Được đăng bởi GP Coder . 14388 Lượt xem . Toàn màn hình

Nội dung

  • 1 Semaphore là gì?
  • 2 Cơ chế hoạt động
  • 3 Ví dụ sử dụng Semaphore
  • 4 Ví dụ sử dụng Mutex

Semaphore là gì?

Semaphore là một cơ chế giúp quản lý các nguồn chia sẻ và đảm bảo access không bị tắc nghẽn.

Có hai loại semaphore: binary semaphore và counting semaphore.

  • Binary semaphore (Mutex): được dùng làm lock vì nó chỉ có 2 giá trị là 0 và 1. Hai giá trị này đại diện cho trạng thái lock hay unlock.
  • Counting semaphore: thực hiện đếm resource để cho biết mức độ sẵn sàng của resource.

Cơ chế hoạt động

Một Semaphore lưu trữ một danh sách các permit (hay ticket), mỗi khi gọi acquire() sẽ lấy 1 ticket từ Semaphore, mỗi khi gọi release() sẽ trả ticket về Semaphore. Nếu ticket không có sẵn, acquire() sẽ bị lock cho đến khi có ticket. Để kiểm tra số lượng ticket còn lại, sử dụng phương thức availablePermits().

Ví dụ chúng ta gọi các phương thức tuần tự như sau:


// Tạo một Semaphore có 5 ticket
Semaphore semaphore = new Semaphore(5);

// Yêu cầu lấy 1 ticket để sử dụng
semaphore.acquire(); // 5-1

// Đếm về số lượng ticket có sẵn
int numberOfAvailableTickets = semaphore.availablePermits(); // 4

// Trả 1 ticket về Semaphore
semaphore.release(); // 4+1

// Đếm về số lượng ticket có sẵn
semaphore.availablePermits(); // 5

Ví dụ sử dụng Semaphore

Giả sử một ngân hàng có 4 cây ATM, mỗi cây chỉ có thể phục vụ được một khách hàng tại một thời điểm. Chương trình bên dưới cho thấy Semaphore có thể đảm bảo chỉ tối đa 4 người có thể truy cập tại một thời điểm.

WorkerThread.java


package com.gpcoder.semaphore;

import java.util.concurrent.Semaphore;

public class WorkerThread extends Thread {

	private final Semaphore semaphore;
	private String name;

	public WorkerThread(Semaphore semaphore, String name) {
		this.semaphore = semaphore;
		this.name = name;
	}

	public void run() {
		try {
			System.out.println(name + ": acquiring lock...");
			System.out.println(name + ": available Semaphore permits now: " + semaphore.availablePermits());
			semaphore.acquire();
			System.out.println(name + ": got the permit!");

			try {
				System.out.println(name + ": is performing operation, available Semaphore permits : "
						+ semaphore.availablePermits());
				Thread.sleep(100); // simulate time to work
			} finally {
				// calling release() after a successful acquire()
				System.out.println(name + ": releasing lock...");
				semaphore.release();
				System.out.println(name + ": available Semaphore permits now: " + semaphore.availablePermits());
			}
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}

SemaphoreExample.java


package com.gpcoder.semaphore;

import java.util.concurrent.Semaphore;

public class SemaphoreExample {

	private static Semaphore semaphore = new Semaphore(4);

	public static void main(String[] args) {
		System.out.println("Total available Semaphore permits: " + semaphore.availablePermits());
		for (int i = 1; i <= 6; i++) {
			WorkerThread atmWorker = new WorkerThread(semaphore, "AMT " + i);
			atmWorker.start();
		}
	}
}

Chạy chương trình trên, ta có kết quả sau:


Total available Semaphore permits: 4
AMT 1: acquiring lock...
AMT 1: available Semaphore permits now: 4
AMT 1: got the permit!
AMT 1: is performing operation, available Semaphore permits : 3
AMT 2: acquiring lock...
AMT 2: available Semaphore permits now: 3
AMT 2: got the permit!
AMT 2: is performing operation, available Semaphore permits : 2
AMT 3: acquiring lock...
AMT 3: available Semaphore permits now: 2
AMT 3: got the permit!
AMT 3: is performing operation, available Semaphore permits : 1
AMT 6: acquiring lock...
AMT 4: acquiring lock...
AMT 4: available Semaphore permits now: 1
AMT 4: got the permit!
AMT 4: is performing operation, available Semaphore permits : 0
AMT 5: acquiring lock...
AMT 5: available Semaphore permits now: 0
AMT 6: available Semaphore permits now: 1
AMT 3: releasing lock...
AMT 4: releasing lock...
AMT 1: releasing lock...
AMT 4: available Semaphore permits now: 2
AMT 2: releasing lock...
AMT 2: available Semaphore permits now: 2
AMT 6: got the permit!
AMT 6: is performing operation, available Semaphore permits : 2
AMT 5: got the permit!
AMT 5: is performing operation, available Semaphore permits : 2
AMT 1: available Semaphore permits now: 3
AMT 3: available Semaphore permits now: 2
AMT 6: releasing lock...
AMT 6: available Semaphore permits now: 3
AMT 5: releasing lock...
AMT 5: available Semaphore permits now: 4

Ví dụ sử dụng Mutex

Mutex là một Semaphore với bộ đếm là 1. Tình huống có thể sử dụng là lock tài khoản khi rút tiền. Tại một thời điểm chỉ 1 thao tác rút tiền được chấp nhận.

Chúng ta sẽ sử dụng lại worker ở trên. Giả sử có 6 user cùng login vào một tài khoản ở các cây ATM khác nhau để thực hiện rút tiền, nếu chúng ta không sử dụng cơ chế synchronized thì cả 6 người đều có thể rút tiền cùng lúc và có thể rút nhiều hơn số tiền hiện có trong tài khoản.

Đoạn code bên dưới sử dụng Mutex giúp chúng ta kiểm soát được vấn đề này một cách dễ dàng.


package com.gpcoder.semaphore;

import java.util.concurrent.Semaphore;

public class MutexExample {

	private static Semaphore semaphore = new Semaphore(1);

	public static void main(String[] args) {
		System.out.println("Total available Semaphore permits: " + semaphore.availablePermits());
		for (int i = 1; i <= 6; i++) {
			WorkerThread atmWorker = new WorkerThread(semaphore, "AMT " + i);
			atmWorker.start();
		}
	}
}

Chạy chương trình trên, chúng ta có kết quả sau:


Total available Semaphore permits: 1
AMT 1: acquiring lock...
AMT 2: acquiring lock...
AMT 1: available Semaphore permits now: 1
AMT 2: available Semaphore permits now: 1
AMT 1: got the permit!
AMT 1: is performing operation, available Semaphore permits : 0
AMT 3: acquiring lock...
AMT 3: available Semaphore permits now: 0
AMT 4: acquiring lock...
AMT 4: available Semaphore permits now: 0
AMT 5: acquiring lock...
AMT 6: acquiring lock...
AMT 6: available Semaphore permits now: 0
AMT 5: available Semaphore permits now: 0
AMT 1: releasing lock...
AMT 1: available Semaphore permits now: 1
AMT 2: got the permit!
AMT 2: is performing operation, available Semaphore permits : 0
AMT 2: releasing lock...
AMT 2: available Semaphore permits now: 0
AMT 3: got the permit!
AMT 3: is performing operation, available Semaphore permits : 0
AMT 3: releasing lock...
AMT 3: available Semaphore permits now: 1
AMT 4: got the permit!
AMT 4: is performing operation, available Semaphore permits : 0
AMT 4: releasing lock...
AMT 6: got the permit!
AMT 6: is performing operation, available Semaphore permits : 0
AMT 4: available Semaphore permits now: 0
AMT 6: releasing lock...
AMT 5: got the permit!
AMT 5: is performing operation, available Semaphore permits : 0
AMT 6: available Semaphore permits now: 0
AMT 5: releasing lock...
AMT 5: available Semaphore permits now: 1

Bài viết đến đây là hết. Hy vọng sau bài viết này các bạn hiểu rõ hơn về Semaphore, cũng như biết cách sử dụng nó trong một số tình huống thích hợp.

Tài liệu tham khảo:

  • https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Semaphore.html
  • https://www.baeldung.com/java-semaphore
  • https://www.mkyong.com/java/java-semaphore-examples/
  • https://www.geeksforgeeks.org/semaphore-in-java/
5.0
22
Nếu bạn thấy hay thì hãy chia sẻ bài viết cho mọi người nhé! Và Donate tác giả

Shares

Chuyên mục: Java Core, Multi-Thread Được gắn thẻ: Basic Java, Multithreading

Tạo số và chuỗi ngẫu nhiên trong Java
Vấn đề Nhà sản xuất (Producer) – Người tiêu dùng (Consumer) và đồng bộ hóa các luồng trong Java

Có thể bạn muốn xem:

  • Lập trình đa luồng trong Java (Java Multi-threading) (12/02/2018)
  • Lập trình đa luồng với CompletableFuture trong Java 8 (19/07/2018)
  • Lập trình đa luồng với Callable và Future trong Java (02/03/2018)
  • Marker Interface trong Java (30/03/2020)
  • Giới thiệu JDBC Connection Pool (14/10/2019)

Bình luận

bình luận

Tìm kiếm

Bài viết mới

  • Clean code 13/01/2024
  • Giới thiệu CloudAMQP – Một RabbitMQ server trên Cloud 02/10/2020
  • Kết nối RabbitMQ sử dụng Web STOMP Plugin 19/06/2020
  • Sử dụng publisher confirm trong RabbitMQ 16/06/2020
  • Sử dụng Dead Letter Exchange trong RabbitMQ 13/06/2020

Xem nhiều

  • Hướng dẫn Java Design Pattern – Factory Method (98056 lượt xem)
  • Hướng dẫn Java Design Pattern – Singleton (97695 lượt xem)
  • Giới thiệu Design Patterns (87758 lượt xem)
  • Lập trình đa luồng trong Java (Java Multi-threading) (86427 lượt xem)
  • Giới thiệu về Stream API trong Java 8 (83830 lượt xem)

Nội dung bài viết

  • 1 Semaphore là gì?
  • 2 Cơ chế hoạt động
  • 3 Ví dụ sử dụng Semaphore
  • 4 Ví dụ sử dụng Mutex

Lưu trữ

Thẻ đánh dấu

Annotation Authentication Basic Java Behavior Pattern Collection Creational Design Pattern Cấu trúc điều khiển Database Dependency Injection Design pattern Eclipse Exception Executor Service Google Guice Gson Hibernate How to Interceptor IO Jackson Java 8 Java Core JDBC JDK Jersey JMS JPA json JUnit JWT Message Queue Mockito Multithreading OOP PowerMockito RabbitMQ Reflection Report REST SOAP Structuaral Pattern Swagger Thread Pool Unit Test Webservice

Liên kết

  • Clean Code
  • JavaTpoint
  • Refactoring Guru
  • Source Making
  • TutorialsPoint
  • W3Schools Online Web Tutorials

Giới thiệu

GP Coder là trang web cá nhân, được thành lập với mục đích lưu trữ, chia sẽ kiến thức đã học và làm việc của tôi. Các bài viết trên trang này chủ yếu về ngôn ngữ Java và các công nghệ có liên quan đến Java như: Spring, JSF, Web Services, Unit Test, Hibernate, SQL, ...
Hi vọng góp được chút ít công sức cho sự phát triển cộng đồng Coder Việt.

Donate tác giả

Tìm kiếm các bài viết của GP Coder với Google Search

Liên hệ

Các bạn có thể liên hệ với tôi thông qua:
  • Trang liên hệ
  • Linkedin: gpcoder
  • Email: contact@gpcoder.com
  • Skype: ptgiang56it

Follow me

Copyright 2025 © GP Coder · All Rights Reserved · Giới thiệu · Chính sách · Điều khoản · Liên hệ ·

Share

Blogger
Delicious
Digg
Email
Facebook
Facebook messenger
Flipboard
Google
Hacker News
Line
LinkedIn
Mastodon
Mix
Odnoklassniki
PDF
Pinterest
Pocket
Print
Reddit
Renren
Short link
SMS
Skype
Telegram
Tumblr
Twitter
VKontakte
wechat
Weibo
WhatsApp
X
Xing
Yahoo! Mail

Copy short link

Copy link