Operating system 二进制信号量和互斥量之间的区别
二进制信号量和互斥量之间有什么区别吗?或者它们本质上是相同的吗?Operating system 二进制信号量和互斥量之间的区别,operating-system,mutex,semaphore,binary-semaphore,Operating System,Mutex,Semaphore,Binary Semaphore,二进制信号量和互斥量之间有什么区别吗?或者它们本质上是相同的吗? 只有获得互斥锁的线程才能释放互斥锁 二进制信号量可以由任何线程(或进程)发出 所以信号量更适合于一些同步问题,比如生产者-消费者 在Windows上,二进制信号量更像事件对象而不是互斥对象。 只有获得互斥锁的线程才能释放互斥锁 二进制信号量可以由任何线程(或进程)发出 所以信号量更适合于一些同步问题,比如生产者-消费者 在Windows上,二进制信号量更像事件对象而不是互斥对象。答案可能取决于目标操作系统。例如,我熟悉的至少一
- 只有获得互斥锁的线程才能释放互斥锁
- 二进制信号量可以由任何线程(或进程)发出
- 只有获得互斥锁的线程才能释放互斥锁
- 二进制信号量可以由任何线程(或进程)发出
在Windows上,二进制信号量更像事件对象而不是互斥对象。答案可能取决于目标操作系统。例如,我熟悉的至少一个RTOS实现将允许对单个OS互斥体执行多个顺序“get”操作,只要它们都来自同一线程上下文。在允许另一个线程获取互斥锁之前,必须将多个get替换为相同数量的put。这与二进制信号量不同,二进制信号量一次只允许一个get,而不管线程上下文如何 这种互斥类型背后的思想是,通过一次只允许单个上下文修改数据来保护对象。即使线程获取互斥量,然后调用一个函数来进一步修改对象(并获取/放置保护器互斥量,使其围绕自己的操作),操作仍然应该是安全的,因为它们都发生在单个线程下
{
mutexGet(); // Other threads can no longer get the mutex.
// Make changes to the protected object.
// ...
objectModify(); // Also gets/puts the mutex. Only allowed from this thread context.
// Make more changes to the protected object.
// ...
mutexPut(); // Finally allows other threads to get the mutex.
}
当然,在使用此功能时,必须确保单个线程中的所有访问都是安全的
我不确定这种方法有多普遍,也不确定它是否适用于我熟悉的系统之外。有关这种互斥的示例,请参阅ThreadX RTO。答案可能取决于目标操作系统。例如,我熟悉的至少一个RTOS实现将允许对单个OS互斥体执行多个顺序“get”操作,只要它们都来自同一线程上下文。在允许另一个线程获取互斥锁之前,必须将多个get替换为相同数量的put。这与二进制信号量不同,二进制信号量一次只允许一个get,而不管线程上下文如何 这种互斥类型背后的思想是,通过一次只允许单个上下文修改数据来保护对象。即使线程获取互斥量,然后调用一个函数来进一步修改对象(并获取/放置保护器互斥量,使其围绕自己的操作),操作仍然应该是安全的,因为它们都发生在单个线程下
{
mutexGet(); // Other threads can no longer get the mutex.
// Make changes to the protected object.
// ...
objectModify(); // Also gets/puts the mutex. Only allowed from this thread context.
// Make more changes to the protected object.
// ...
mutexPut(); // Finally allows other threads to get the mutex.
}
当然,在使用此功能时,必须确保单个线程中的所有访问都是安全的
我不确定这种方法有多普遍,也不确定它是否适用于我熟悉的系统之外。有关这种互斥的示例,请参阅ThreadX RTO。它们不是同一件事。它们用于不同的目的
虽然这两种类型的信号量都有一个满/空状态,并且使用相同的API,但它们的用法非常不同 互斥信号量
互斥信号用于保护共享资源(数据结构、文件等) 互斥信号量由接收它的任务“拥有”。如果任务B尝试提供任务a当前持有的互斥锁,则任务B的调用将返回错误并失败 互斥锁始终使用以下顺序: - SemTake - Critical Section - SemGive -塞姆塔克 -临界截面 -塞姆吉奇 下面是一个简单的例子: Thread A Thread B Take Mutex access data ... Take Mutex <== Will block ... Give Mutex access data <== Unblocks ... Give Mutex 螺纹A螺纹B 接受互斥 访问数据
... 以互斥体为例,它们是不同的。它们用于不同的目的
虽然这两种类型的信号量都有一个满/空状态,并且使用相同的API,但它们的用法非常不同 互斥信号量
互斥信号用于保护共享资源(数据结构、文件等) 互斥信号量由接收它的任务“拥有”。如果任务B尝试提供任务a当前持有的互斥锁,则任务B的调用将返回错误并失败 互斥锁始终使用以下顺序: - SemTake - Critical Section - SemGive -塞姆塔克 -临界截面 -塞姆吉奇 下面是一个简单的例子: Thread A Thread B Take Mutex access data ... Take Mutex <== Will block ... Give Mutex access data <== Unblocks ... Give Mutex 螺纹A螺纹B 接受互斥 访问数据
... 以互斥对象为例,它们的同步语义非常不同:
- 互斥锁允许序列化对给定资源的访问,即多个线程等待锁,一次一个,如前所述,线程拥有锁,直到锁完成:只有此特定线程可以解锁它
- 二进制信号量是一个值为0和1的计数器:一个任务在它上面阻塞,直到any任务执行sem\u post。信号量通知资源可用,并提供等待机制,直到通知资源可用为止
因此,可以将互斥体视为从一个任务传递到另一个任务的令牌,将信号量视为交通红灯(它向某人发出可以继续的信号)。它们的同步语义非常不同:
- 互斥锁允许序列化对给定资源的访问,即多个线程等待锁,一次一个,如前所述,线程拥有锁,直到锁完成:只有此特定线程可以解锁它
- 二进制信号量是一个值为0和1的计数器:一个任务阻塞它直到一个
#include <stdio.h> #include <windows.h> #define xUSE_MUTEX 1 #define MAX_SEM_COUNT 1 DWORD WINAPI Thread_no_1( LPVOID lpParam ); DWORD WINAPI Thread_no_2( LPVOID lpParam ); HANDLE Handle_Of_Thread_1 = 0; HANDLE Handle_Of_Thread_2 = 0; int Data_Of_Thread_1 = 1; int Data_Of_Thread_2 = 2; HANDLE ghMutex = NULL; HANDLE ghSemaphore = NULL; int main(void) { #ifdef USE_MUTEX ghMutex = CreateMutex( NULL, FALSE, NULL); if (ghMutex == NULL) { printf("CreateMutex error: %d\n", GetLastError()); return 1; } #else // Create a semaphore with initial and max counts of MAX_SEM_COUNT ghSemaphore = CreateSemaphore(NULL,MAX_SEM_COUNT,MAX_SEM_COUNT,NULL); if (ghSemaphore == NULL) { printf("CreateSemaphore error: %d\n", GetLastError()); return 1; } #endif // Create thread 1. Handle_Of_Thread_1 = CreateThread( NULL, 0,Thread_no_1, &Data_Of_Thread_1, 0, NULL); if ( Handle_Of_Thread_1 == NULL) { printf("Create first thread problem \n"); return 1; } /* sleep for 5 seconds **/ Sleep(5 * 1000); /*Create thread 2 */ Handle_Of_Thread_2 = CreateThread( NULL, 0,Thread_no_2, &Data_Of_Thread_2, 0, NULL); if ( Handle_Of_Thread_2 == NULL) { printf("Create second thread problem \n"); return 1; } // Sleep for 20 seconds Sleep(20 * 1000); printf("Out of the program \n"); return 0; } int my_critical_section_code(HANDLE thread_handle) { #ifdef USE_MUTEX if(thread_handle == Handle_Of_Thread_1) { /* get the lock */ WaitForSingleObject(ghMutex, INFINITE); printf("Thread 1 holding the mutex \n"); } #else /* get the semaphore */ if(thread_handle == Handle_Of_Thread_1) { WaitForSingleObject(ghSemaphore, INFINITE); printf("Thread 1 holding semaphore \n"); } #endif if(thread_handle == Handle_Of_Thread_1) { /* sleep for 10 seconds */ Sleep(10 * 1000); #ifdef USE_MUTEX printf("Thread 1 about to release mutex \n"); #else printf("Thread 1 about to release semaphore \n"); #endif } else { /* sleep for 3 secconds */ Sleep(3 * 1000); } #ifdef USE_MUTEX /* release the lock*/ if(!ReleaseMutex(ghMutex)) { printf("Release Mutex error in thread %d: error # %d\n", (thread_handle == Handle_Of_Thread_1 ? 1:2),GetLastError()); } #else if (!ReleaseSemaphore(ghSemaphore,1,NULL) ) { printf("ReleaseSemaphore error in thread %d: error # %d\n",(thread_handle == Handle_Of_Thread_1 ? 1:2), GetLastError()); } #endif return 0; } DWORD WINAPI Thread_no_1( LPVOID lpParam ) { my_critical_section_code(Handle_Of_Thread_1); return 0; } DWORD WINAPI Thread_no_2( LPVOID lpParam ) { my_critical_section_code(Handle_Of_Thread_2); return 0; }
pthread_mutex_t mutex; pthread_mutexattr_t attr; pthread_mutexattr_init (&attr); pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_ERRORCHECK_NP); pthread_mutex_init (&mutex, &attr);
if(pthread_mutex_unlock(&mutex)==EPERM) printf("Unlock failed:Mutex not owned by this thread\n");