(1)互斥锁
允许程序员锁住某个对象,使得每次只能有一个线程访问他。为了控制关键代码的访问,必须在进入这段代码之前锁住一个互斥量,然后再完成操作之后解锁它。
用于互斥锁的基本函数:
#include<stdio.h>
int pthread_mutex_init(pthread_mutex_t *mutex,const pthread_mutexattr_t *mutexattr);//初始化
int pthread_mutex_lock(pthread_mutex_t *mutex);//加锁
int pthread_mutex_unlock(pthread_mutex_t *mutex);//解锁
int pthread_mutex_destroy(pthread_mutex_t *mutex);//销毁锁
用互斥锁解决上面问题:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <assert.h>
#include <pthread.h>
pthread_mutex_t mutex;
char buff[128]={0};
void *fun(void *arg)
{
while(1)
{
pthread_mutex_lock(&mutex);
int i=0;
int count=0;
for(;i<strlen(buff);++i)
{
if(isalpha(buff[i]) && !isalpha(buff[i+1]))
{
count++;
}
}
printf("count == %d\n",count);
pthread_mutex_unlock(&mutex);
sleep(1);
}
}
void main()
{
pthread_mutex_init(&mutex,NULL);
pthread_t id;
int res=pthread_create(&id,NULL,fun,NULL);
assert(res==0);
while(1)
{
pthread_mutex_lock(&mutex);
printf("Input: \n");
fflush(stdout);
fgets(buff,128,stdin);
buff[strlen(buff)-1]=0;
if(strncmp(buff,"end",3)==0)
{
break;
}
pthread_mutex_unlock(&mutex);
sleep(1);
}
}
(2)信号量
信号量的基本函数:
#include<semaphore.h>
int sem_init(sem_t *sem,int pshared,unisigned int value);//初始化
int sem_wait(sem_t *sem);//相当于进程中的P操作
int sem_post(sem_t *sem);//相当于进程中的V操作
int sem_destroy(sem_t *sem);//用完信号良好对它进行清理
针对上面用互斥锁解决的问题,用信号量解决,代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <assert.h>
#include <pthread.h>
#include <semaphore.h>
sem_t sem;
char buff[128]={0};
void *fun(void *arg)
{
while(1)
{
sem_wait(&sem);
int i=0;
int count=0;
for(;i<strlen(buff);++i)
{
if(isalpha(buff[i]) && !isalpha(buff[i+1]))
{
count++;
}
}
printf("count == %d\n",count);
}
}
void main()
{
sem_init(&sem,0,0);
pthread_t id;
int res=pthread_create(&id,NULL,fun,NULL);
assert(res==0);
while(1)
{
printf("Input: \n");
fflush(stdout);
fgets(buff,128,stdin);
buff[strlen(buff)-1]=0;
if(strncmp(buff,"end",3)==0)
{
break;
}
sem_post(&sem);
}
}
(3)读写锁
基本函数
ReadWriterLock rwlock = new ReentranReadWriterLock();
rwlock.writeLock().lock(); //获得写入操作的锁,并上锁
//写入操作执行
rwlock.writeLock().unlock(); //获得写入操作的锁,并解锁
rwlock.readLock().lock(); //获取读取操作的锁,并上锁
//读取操作执行
rwlock.readLock().unlock(); //获取读取操作的锁,并解锁
代码实现
class ReadWrite {
//共享数据,只能一个线程写数据,可以多个线程读数据
private Object data = null;
//创建一个读写锁
ReadWriteLock rwlock = new ReentrantReadWriteLock();
Lock r = rwlock.readLock(); //读锁
Lock w = rwlock.writeLock(); //写锁
public void get() {
r.lock(); //读上锁
try {
System.out.println(Thread.currentThread().getName() + "**准备读数据!");
Thread.sleep((long) (Math.random() * 1000)); //模拟读操作
System.out.println(Thread.currentThread().getName() + "---------读出的数据为 :" + data);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
r.unlock();
}
}
public void put(Object data) {
w.lock(); //写上锁
try {
System.out.println(Thread.currentThread().getName() + " +++++++准备写数据!");
Thread.sleep((long) (Math.random() * 1000)); //模拟写操作
this.data = data;
System.out.println(Thread.currentThread().getName() + " ........写入的数据: " + data);
} catch (Exception e) {
e.printStackTrace();
} finally {
w.unlock();
}
}
}
public class ReentrantReadWriterLockTest{
public static void main(String[] args) {
final ReadWrite readWrite = new ReadWrite();
for (int i = 0; i < 3; i++) { //创建并启动3个读线程
new Thread(new Runnable() {
@Override
public void run() {
readWrite.put(new Random().nextInt(8)); //随机写入一个数据
}
}).start();
}
for(int i=0;i<9;i++){ //创建并启动了9个写线程
new Thread(new Runnable() {
@Override
public void run() {
readWrite.get();
}
}).start();
}
}
}