Linux线程共享技巧:探讨句柄的应用 (linux 线程 共享 句柄)

操作系统的本质是为了管理硬件资源,提供给应用程序统一的接口,使得应用程序可以直接使用硬件资源,而不需要过多关注底层硬件的细节。线程是应用程序中非常重要的概念,它可以让应用程序变得高效和可靠。在Linux系统中,线程也是重要的概念之一,它对应的就是轻量级进程(LWP)。Linux系统中线程的创建和销毁都比较容易,但是如何实现线程间的共享,则需要使用到一些技巧,其中之一就是句柄的应用。

句柄是一种抽象的概念,通常表示一些资源的标识符。在Linux系统中,许多资源都可以通过句柄来进行描述和处理,比如文件、套接字、管道等等。在多线程环境中,句柄被广泛应用在线程间的共享中,可以让不同的线程共享同一个句柄,从而实现资源的共享。

下面通过一个简单的例子来说明如何利用句柄实现线程间的共享。假设有两个线程,分别代表两个进程,要共享一个共享内存区域,代码如下:

“`

#include

#include

#include

#include

#include

#include

#include

#include

#define SHM_SIZE 1024

void *thread1(void *arg);

void *thread2(void *arg);

int shmid;

int mn(int argc, char **argv)

{

pthread_t tid1, tid2;

shmid = shmget(IPC_PRIVATE, SHM_SIZE, IPC_CREAT | 0666);

if (shmid == -1) {

perror(“shmget”);

exit(EXIT_FLURE);

}

if (pthread_create(&tid1, NULL, thread1, NULL) != 0) {

perror(“pthread_create”);

exit(EXIT_FLURE);

}

if (pthread_create(&tid2, NULL, thread2, NULL) != 0) {

perror(“pthread_create”);

exit(EXIT_FLURE);

}

if (pthread_join(tid1, NULL) != 0) {

perror(“pthread_join”);

exit(EXIT_FLURE);

}

if (pthread_join(tid2, NULL) != 0) {

perror(“pthread_join”);

exit(EXIT_FLURE);

}

if (shmctl(shmid, IPC_RMID, NULL) == -1) {

perror(“shmctl”);

exit(EXIT_FLURE);

}

exit(EXIT_SUCCESS);

}

void *thread1(void *arg)

{

void *shmaddr;

shmaddr = shmat(shmid, NULL, 0);

if (shmaddr == (void *)-1) {

perror(“shmat”);

exit(EXIT_FLURE);

}

printf(“Thread1 attach shared-memory\n”);

strcpy(shmaddr, “Hello, world!\n”);

pthread_exit(NULL);

}

void *thread2(void *arg)

{

void *shmaddr;

usleep(500000);

shmaddr = shmat(shmid, NULL, 0);

if (shmaddr == (void *)-1) {

perror(“shmat”);

exit(EXIT_FLURE);

}

printf(“Thread2 attach shared-memory\n”);

printf(“Message: %s\n”, (char *)shmaddr);

pthread_exit(NULL);

}

“`

上面的代码创建了两个线程,一个线程用来写入共享内存区域,另一个线程用来读取共享内存区域,并将读取到的内容打印出来。可以看到,两个线程都通过shmat函数获取共享内存区域的地址,从而可以对该共享内存进行读写操作。在这个例子中,shmat函数返回的就是共享内存区域的句柄,两个线程都拥有该句柄,并利用它来共享内存。

这个例子虽然简单,但也说明了句柄在Linux线程间共享中的重要性。句柄的应用使得不同的线程可以共享同一资源,从而提高了线程的利用率和系统的可靠性。当然,在使用句柄时,需要注意同步和错误处理的问题,否则可能会出现一些难以预料的问题。

相关问题拓展阅读:

Linux C++多线程同步的四种方式

From :

1.同一个线程内部,指令按照先后顺序执行;但不同线程之间的指令很难说清楚是哪一个先执行,在并况下,指令执行的先后顺序由内核决定。

如果运行的结果依赖于不同线程执行的先后的话,那么就会形成竞争条件,在这样的情况下,计算的结果很难预知,所以应该尽量避免竞争条件的形成。

2.最常见的解决竞争条件的方法是:将原先分离的两个指令构成一个不可分割的原子操作,而其他任务不能插入到原子操作中!

3.对

多线程

来说,同步指的是在一定时间内只允许某一个线程访问某个资源,而在此时间内,不允许其他线程访问该资源!

互斥锁

条件变量

读写锁

信号量

一种特殊的

全局变量

,拥有lock和unlock两种状态。

unlock的互斥锁可以由某个线程获得,一旦获得,这个互斥锁会锁上变成lock状态,此后只有该线程由权力打开该锁,其他线程想要获得互斥锁,必须得到互斥锁再次被打开之后。

1.互斥锁的初始化, 分为静态初始化和动态初始化.

2.互斥锁的相关属性及分类

(1) attr表示互斥锁的属性;

(2) pshared表示互斥锁的共享属性,由两种取值:

1)PTHREAD_PROCESS_PRIVATE:锁只能用于一个进程内部的两个线程进行互斥(默认情况)

2)PTHREAD_PROCESS_SHARED:锁可用于两个不同进程中的线程进行互斥,使用时还需要在进程共享内存中分配互斥锁,然后为该互斥锁指定属性就可以了。

互斥锁存在缺点:

(1)某个线程正在等待共享数据内某个条件出现。

(2)重复对数据对象加锁和解锁(轮询),但是这样轮询非常耗费时间和资源,而且效率非常低,所以互斥锁不太适合这种情况。

当线程在等待满足某些条件时,使线程进入睡眠状态;一旦条件满足,就换线因等待满足特定条件而睡眠的线程。

程序的效率无疑会大大提高。

1)创建

静态方式:pthread_cond_t cond PTHREAD_COND_INITIALIZER

动态方式:int pthread_cond_init(&cond,NULL)

Linux thread 实现的条件变量不支持属性,所以NULL(cond_attr参数)

2)注销

int pthread_cond_destory(&cond)

只有没有线程在该条件变量上,该条件变量才能注饥亩销,否则返回EBUSY

因为Linux实现的条件变量没有分配什么资源,所以注销动作只包括检查是否姿肢改有等待线程!(请参考条件变量的底层实现)

3)等待

条件等待:int pthread_cond_wait(&cond,&mutex)

计时等待:int pthread_cond_timewait(&cond,&mutex,time)

1.其中计时等待如果在给定时刻前条件没有被满足,则返回ETIMEOUT,结束等待

2.无论那种等待方式,都必须有一个互斥锁配合,以防止多个线程同时请求pthread_cond_wait形成竞争条件!

3.在调用pthread_cond_wait前必须由本线程加锁

4)激发

激发一个等待线程:pthread_cond_signal(&cond)

激发所有等待线程:pthread_cond_broadcast(&cond)

重要的是,pthread_cond_signal不会存在惊群效应,也就是是它最多给一个等待线程发信号,不会给所有线程发信号唤醒,然后要求他们自己去争抢资源!

pthread_cond_broadcast() 唤醒所有正在pthread_cond_wait()的同一个条件变量的线程。注意:如果等待的多个现场不使用同一个锁,被唤迹判醒的多个线程执行是并发的。

pthread_cond_broadcast & pthread_cond_signal

1.读写锁比互斥锁更加具有适用性和并行性

2.读写锁最适用于对

数据结构

的读操作读操作次数多余写操作次数的场合!

3.锁处于读模式时可以线程共享,而锁处于写模式时只能独占,所以读写锁又叫做共享-独占锁。

4.读写锁有两种策略:强读同步和强写同步

强读同步:

总是给读者更高的优先权,只要写者没有进行写操作,读者就可以获得访问权限

强写同步:

总是给写者更高的优先权,读者只能等到所有正在等待或者执行的写者完成后才能进行读

1)初始化的销毁读写锁

静态初始化:pthread_rwlock_t rwlock=PTHREAD_RWLOCK_INITIALIZER

动态初始化:int pthread_rwlock_init(rwlock,NULL),NULL代表读写锁采用默认属性

销毁读写锁:int pthread_rwlock_destory(rwlock)

在释放某个读写锁的资源之前,需要先通过pthread_rwlock_destory函数对读写锁进行清理。释放由pthread_rwlock_init函数分配的资源

如果你想要读写锁使用非默认属性,则attr不能为NULL,得给attr赋值

int pthread_rwlockattr_init(attr),给attr初始化

int pthread_rwlockattr_destory(attr),销毁attr

2)以写的方式获取锁,以读的方式获取锁,释放读写锁

int pthread_rwlock_rdlock(rwlock),以读的方式获取锁

int pthread_rwlock_wrlock(rwlock),以写的方式获取锁

int pthread_rwlock_unlock(rwlock),释放锁

上面两个获取锁的方式都是阻塞的函数,也就是说获取不到锁的话,调用线程不是立即返回,而是阻塞执行,在需要进行写操作的时候,这种阻塞式获取锁的方式是非常不好的,你想一下,我需要进行写操作,不但没有获取到锁,我还一直在这里等待,大大拖累效率

所以我们应该采用非阻塞的方式获取锁:

int pthread_rwlock_tryrdlock(rwlock)

int pthread_rwlock_trywrlock(rwlock)

互斥锁只允许一个线程进入临界区,而信号量允许多个线程进入临界区。

1)信号量初始化

int sem_init(&sem,pshared, v)

pshared为0,表示这个信号量是当前进程的局部信号量。

pshared为1,表示这个信号量可以在多个进程之间共享。

v为信号量的初始值。

返回值

成功:0,失败:-1

2)信号量值的加减

int sem_wait(&sem):以原子操作的方式将信号量的值减去1

int sem_post(&sem):以原子操作的方式将信号量的值加上1

3)对信号量进行清理

int sem_destory(&sem)

关于linux 线程 共享 句柄的介绍到此就结束了,不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息,记得收藏关注本站。


数据运维技术 » Linux线程共享技巧:探讨句柄的应用 (linux 线程 共享 句柄)