线程同步以及线程间通信

线程同步以及线程间通信是多线程编程中必不可少的概念。本文将详细介绍线程同步和线程间通信的相关知识。

一、线程同步

在多线程编程中,当多个线程同时访问共享资源时,会产生竞争条件(Race Condition),导致程序出现错误或异常情况。线程同步机制是为了解决这个问题而设计的。其基本思想是通过控制对共享资源的访问,使得它们能够安全地被多个线程共享。下面介绍三种常用的线程同步机制。

  1. 互斥锁

互斥锁(Mutex)是最常用的线程同步技术之一,它保证在同一时间只有一个线程可以访问共享资源。当一个线程获得了互斥锁后,其他线程必须等待该线程释放锁才能获得。

在 Linux C++ 中,使用 pthread_mutex_t 数据类型来表示互斥锁。下面是一个互斥锁的例子:

#include <pthread.h>
#include <iostream>

using namespace std;

pthread_mutex_t mutex; //定义互斥锁

void *thread_function(void *arg)
{
    int i;
    for (i = 0; i < 5; i++)
    {
        pthread_mutex_lock(&mutex); //加锁
        cout << "Thread " << pthread_self() << " is running\n";
        pthread_mutex_unlock(&mutex); //释放锁
    }
    return NULL;
}

int main()
{
    pthread_t thread1, thread2;

    pthread_mutex_init(&mutex, NULL); //初始化互斥锁

    pthread_create(&thread1, NULL, thread_function, NULL);
    pthread_create(&thread2, NULL, thread_function, NULL);

    pthread_join(thread1, NULL);
    pthread_join(thread2, NULL);

    pthread_mutex_destroy(&mutex); //销毁互斥锁
    return 0;
}
  1. 条件变量

条件变量(Condition Variable)是一种线程同步机制,用于线程之间的通信。它允许某个线程等待另外一个线程的通知,而无需使用忙等待(Busy Waiting)的方式来等待。

在 Linux C++ 中,使用 pthread_cond_t 数据类型来表示条件变量。下面是一个条件变量的例子:

#include <pthread.h>
#include <iostream>

using namespace std;

pthread_mutex_t mutex; //定义互斥锁
pthread_cond_t cond = PTHREAD_COND_INITIALIZER; //初始化条件变量

void *thread_function(void *arg)
{
    cout << "Thread " << pthread_self() << " waiting...\n";
    pthread_mutex_lock(&mutex); //加锁
    pthread_cond_wait(&cond, &mutex); //等待条件变量
    cout << "Thread " << pthread_self() << " is running\n";
    pthread_mutex_unlock(&mutex); //释放锁
    return NULL;
}

int main()
{
    pthread_t thread;

    pthread_mutex_init(&mutex, NULL); //初始化互斥锁

    pthread_create(&thread, NULL, thread_function, NULL);

    sleep(2); //等待两秒钟

    cout << "Signal...\n"; //发出通知信号
    pthread_mutex_lock(&mutex); //加锁
    pthread_cond_signal(&cond); //发出条件变量信号
    pthread_mutex_unlock(&mutex); //释放锁

    pthread_join(thread, NULL);

    pthread_mutex_destroy(&mutex); //销毁互斥锁
    pthread_cond_destroy(&cond); //销毁条件变量

    return 0;
}
  1. 读写锁

读写锁(Reader-Writer Lock)是一种特殊的互斥锁,用于解决多读单写场景下的性能问题。读写锁允许多个线程同时读取共享资源,但只允许一个线程写入共享资源。

在 Linux C++ 中,使用 pthread_rwlock_t 数据类型来表示读写锁。下面是一个读写锁的例子:

#include <pthread.h>
#include <iostream>

using namespace std;

pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER; //初始化读写锁

void *reader_function(void *arg)
{
    pthread_rwlock_rdlock(&rwlock); //以读模式加锁
    cout << "Reader " << pthread_self() << " is reading...\n";
    sleep(2);
    pthread_rwlock_unlock(&rwlock); //释放锁
    return NULL;
}

void *writer_function(void *arg)
{
    pthread_rwlock_wrlock(&rwlock); //以写模式加锁
    cout << "Writer " << pthread_self() << " is writing...\n";
    sleep(2);
    pthread_rwlock_unlock(&rwlock); //释放锁
    return NULL;
}

int main()
{
    pthread_t reader1, reader2, writer;

    pthread_create(&reader1, NULL, reader_function, NULL);
    pthread_create(&reader2, NULL, reader_function, NULL);
    pthread_create(&writer, NULL, writer_function, NULL);

    pthread_join(reader1, NULL);
    pthread_join(reader2, NULL);
    pthread_join(writer, NULL);

    pthread_rwlock_destroy(&rwlock); //销毁读写锁

    return 0;
}

二、线程间通信

线程间通信(Inter-Thread Communication)是指多个线程之间通过某种方式来交换信息,并协同完成某个任务。下面介绍三种常用的线程间通信机制。

  1. 管道

管道(Pipe)是一种基于文件描述符的进程间通信方式,也可以被应用于线程间通信。在 Linux C++ 中,管道由两端组成,分别是读端和写端。一个线程向管道中写入数据,另一个线程从管道中读取数据。

下面是一个管道的例子:

#include <unistd.h>
#include <iostream>

using namespace std;

int pipefd[2];

void *write_function(void *arg)
{
    char buffer[] = "Hello, world!";
    write(pipefd[1], buffer, sizeof(buffer)); //向管道中写入数据
    return NULL;
}

void *read_function(void *arg)
{
    char buffer[256];
    read(pipefd[0], buffer, sizeof(buffer)); //从管道中读取数据
    cout << "Receive data: " << buffer << endl;
    return NULL;
}

int main()
{
    pthread_t thread1, thread2;

    pipe(pipefd); //创建管道

    pthread_create(&thread1, NULL, write_function, NULL);
    pthread_create(&thread2, NULL, read_function, NULL);

    pthread_join(thread1, NULL);
    pthread_join(thread2, NULL);

    close(pipefd[0]); //关闭管道
    close(pipefd[1]);

    return 0;
}
  1. 共享内存

共享内存(Shared Memory)是一种进程间通信方式,也可以被用于线程间通信。它指多个线程可同时访问的一块系统内存。

在 Linux C++ 中,可以使用 shmget、shmat 和 shmdt 等函数来操作共享内存。下面是一个共享内存的例子:

#include <sys/shm.h>
#include <iostream>

using namespace std;

const int SHM_SIZE = 1024;

int main()
{
    int shmid;
    char *shmaddr;

    shmid = shmget(IPC_PRIVATE, SHM_SIZE, IPC_CREAT|0600); //创建一块共享内存
    shmaddr = (char*)shmat(shmid, NULL, 0); //将共享内存映射至进程的地址空间

    strcpy(shmaddr, "Hello, world!"); //向共享内存中写入数据
    cout << "Data in shared memory: " << shmaddr << endl;

    shmdt((void*)shmaddr); //将共享内存从进程的地址空间中解除映射
    shmctl(shmid, IPC_RMID, NULL); //销毁共享内存

    return 0;
}
  1. 消息队列

消息队列(Message Queue)是一种进程间通信方式,也可以被用于线程间通信。它通过一个由操作系统维护的消息队列来传递数据。发送线程向消息队列中写入数据,接收线程从消息队列中读取数据。

在 Linux C++ 中,可以使用 msgget、msgsnd 和 msgrcv 等函数来操作消息队列。下面是一个消息队列的例子:

#include <sys/ipc.h>
#include <sys/msg.h>
#include <iostream>

using namespace std;

const int MSG_SIZE = 1024;

struct Message
{
    long mtype;
    char mtext[MSG_SIZE];
};

int main()
{
    key_t key;
    int msgid;
    Message message;

    key = ftok(".", 'a'); //生成一个键值
    msgid = msgget(key, IPC_CREAT|0600); //创建消息队列

    message.mtype = 1; //设置消息类型
    strcpy(message.mtext, "Hello, world!"); //设置消息内容
    msgsnd(msgid, &message, sizeof(message), 0); //发送消息

    msgrcv(msgid, &message, sizeof(message), 0, 0); //接收消息
    cout << "Receive data: " << message.mtext << endl;

    msgctl(msgid, IPC_RMID, NULL); //销毁消息队列

    return 0;
}

猜你喜欢

转载自blog.csdn.net/CarryMee/article/details/131119849
今日推荐