信号量和读写锁的区别
时间: 2024-06-20 20:01:21 浏览: 9
信号量和读写锁都是并发控制机制,用于解决多个线程对共享资源的竞争访问问题。它们的主要区别在于如何管理资源的读取和写入操作。
1. **信号量**(Semaphore):
- 信号量通常是一个整数值,代表资源的可用数量。当一个线程请求使用资源时,会检查信号量的值是否大于0,如果是,则减1并继续;否则,线程被阻塞,直到信号量增加。
- 信号量支持互斥访问,即一次只有一个线程可以执行对资源的修改操作(相当于独占锁),而读取操作则不受限,多个线程可以同时读取。
- 信号量没有专门区分读写操作,处理所有的请求都是一致的。
2. **读写锁**(Read-Write Lock):
- 读写锁包含两种类型的锁:读锁和写锁。读锁允许多个线程同时读取资源,写锁仅允许一个线程进行写操作,读写操作不可并发。
- 当有写操作时,其他所有线程(无论是读还是写)都会被阻塞,直到写操作完成。
- 读锁可以同时存在多个,但写锁只有一个,这就意味着多个读线程可以同时运行,但写线程必须独占资源。
相关问题
基于rt thread 的信号量实现读写锁的控制结构体和相关API函数
RT-Thread中可以使用信号量实现读写锁,具体实现方式如下所示:
```c
/* 定义读写锁结构体 */
typedef struct
{
rt_sem_t lock; // 读写锁信号量
rt_sem_t write_sem; // 写入信号量
int reader_count; // 读者数量
} rt_rwlock_t;
/* 初始化读写锁 */
void rt_rwlock_init(rt_rwlock_t *rwlock)
{
rwlock->lock = rt_sem_create("rwlock", 1, RT_IPC_FLAG_FIFO); // 初始化为1,表示可用
rwlock->write_sem = rt_sem_create("write_sem", 1, RT_IPC_FLAG_FIFO);
rwlock->reader_count = 0;
}
/* 获取读锁 */
void rt_rwlock_read_lock(rt_rwlock_t *rwlock)
{
rt_sem_take(rwlock->lock, RT_WAITING_FOREVER); // 加锁,防止其他线程修改reader_count
rwlock->reader_count++;
if (rwlock->reader_count == 1)
{
rt_sem_take(rwlock->write_sem, RT_WAITING_FOREVER); // 如果是第一个读者,需要获取写入锁
}
rt_sem_release(rwlock->lock); // 解锁
}
/* 释放读锁 */
void rt_rwlock_read_unlock(rt_rwlock_t *rwlock)
{
rt_sem_take(rwlock->lock, RT_WAITING_FOREVER); // 加锁,防止其他线程修改reader_count
rwlock->reader_count--;
if (rwlock->reader_count == 0)
{
rt_sem_release(rwlock->write_sem); // 如果没有读者了,释放写入锁
}
rt_sem_release(rwlock->lock); // 解锁
}
/* 获取写锁 */
void rt_rwlock_write_lock(rt_rwlock_t *rwlock)
{
rt_sem_take(rwlock->write_sem, RT_WAITING_FOREVER); // 获取写入锁
}
/* 释放写锁 */
void rt_rwlock_write_unlock(rt_rwlock_t *rwlock)
{
rt_sem_release(rwlock->write_sem); // 释放写入锁
}
```
上述代码中,读写锁结构体包含一个读写锁信号量、一个写入信号量、一个读者数量。在获取读锁时,需要先获取读写锁信号量,然后增加读者数量,如果是第一个读者,需要获取写入信号量。在释放读锁时,需要先获取读写锁信号量,然后减少读者数量,如果没有读者了,需要释放写入信号量。在获取写锁时,只需要获取写入信号量。在释放写锁时,只需要释放写入信号量。
需要注意的是,在使用读写锁时,需要确保读者和写者之间的互斥性,即不能同时存在读者和写者。因此,在获取写锁时,需要等待所有的读者完成读操作后才能获取锁。这里的实现方式是使用了一个写入信号量来实现这个功能。
基于rt thread 的信号量实现读写锁的控制结构体和相关API函数,要求条理清晰
首先,需要定义一个结构体来表示读写锁的控制结构,如下所示:
```c
typedef struct rwlock
{
rt_uint16_t read_count; // 读者数量
rt_uint16_t write_count; // 写者数量
rt_sem_t read_sem; // 读信号量
rt_sem_t write_sem; // 写信号量
} rwlock_t;
```
其中,`read_count` 表示当前有多少个读者正在读取数据,`write_count` 表示当前有多少个写者正在修改数据,`read_sem` 是用来控制读者的信号量,`write_sem` 是用来控制写者的信号量。
接下来,定义相关的 API 函数:
```c
void rwlock_init(rwlock_t *lock);
void rwlock_read_lock(rwlock_t *lock);
void rwlock_read_unlock(rwlock_t *lock);
void rwlock_write_lock(rwlock_t *lock);
void rwlock_write_unlock(rwlock_t *lock);
```
其中,`rwlock_init` 用于初始化读写锁,`rwlock_read_lock` 和 `rwlock_write_lock` 分别用于获取读锁和写锁,`rwlock_read_unlock` 和 `rwlock_write_unlock` 分别用于释放读锁和写锁。
下面是具体实现:
```c
void rwlock_init(rwlock_t *lock)
{
lock->read_count = 0;
lock->write_count = 0;
rt_sem_init(&(lock->read_sem), "read_sem", 0, RT_IPC_FLAG_FIFO);
rt_sem_init(&(lock->write_sem), "write_sem", 1, RT_IPC_FLAG_FIFO);
}
void rwlock_read_lock(rwlock_t *lock)
{
rt_sem_take(&(lock->write_sem), RT_WAITING_FOREVER);
rt_atomic_inc(&(lock->read_count));
if (lock->read_count == 1)
{
rt_sem_take(&(lock->read_sem), RT_WAITING_FOREVER);
}
rt_sem_release(&(lock->write_sem));
}
void rwlock_read_unlock(rwlock_t *lock)
{
rt_atomic_dec(&(lock->read_count));
if (lock->read_count == 0)
{
rt_sem_release(&(lock->read_sem));
}
}
void rwlock_write_lock(rwlock_t *lock)
{
rt_sem_take(&(lock->write_sem), RT_WAITING_FOREVER);
rt_atomic_inc(&(lock->write_count));
if (lock->write_count == 1)
{
rt_sem_take(&(lock->read_sem), RT_WAITING_FOREVER);
}
rt_sem_release(&(lock->write_sem));
}
void rwlock_write_unlock(rwlock_t *lock)
{
rt_atomic_dec(&(lock->write_count));
if (lock->write_count == 0)
{
rt_sem_release(&(lock->read_sem));
}
}
```
在实现读锁和写锁的时候,需要注意以下几点:
1. 获取读锁时,需要先获取写锁,然后再增加读者数量,如果是第一个读者,需要获取读信号量。
2. 释放读锁时,需要减少读者数量,如果没有读者,需要释放读信号量。
3. 获取写锁时,需要先获取写锁,然后再增加写者数量,如果是第一个写者,需要获取读信号量。
4. 释放写锁时,需要减少写者数量,如果没有写者,需要释放读信号量。
这样就实现了一个基于 rt thread 的读写锁。
相关推荐
![zip](https://img-home.csdnimg.cn/images/20210720083736.png)
![docx](https://img-home.csdnimg.cn/images/20210720083331.png)
![doc](https://img-home.csdnimg.cn/images/20210720083327.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)