Linux和Windows之间多线程的异同

电脑杂谈  发布时间:2020-06-22 22:14:14  来源:网络整理

linux用不了多线程_linux 线程 pthread_create_linux的进程与线程

Linux多线程与线程同步与Windows多线程之间的异同

并非所有程序都必须使用多线程,有时多线程的性能不如单线程. 使用多线程的好处如下:

(1)多线程使用相同的地址空间并共享大多数数据. 与多进程相比,成本更为节省,并且必须将启动一个新进程分配给其独立的地址空间,这需要一个数据表. 维护代码段,数据段,堆栈段等.

(2)对于不同的进程,它们具有独立的数据空间,并且只能通过通信进行数据传输,这既费时又不方便. 数据可以在多个线程之间直接共享,例如共享全局变量. 共享全局变量时,应注意变量的同步性,否则容易造成灾难性后果.

(3)在有多个CPU的情况下,不同的线程可以在不同的CPU下运行,因此它们是完全并行的.

在这种情况下,多线程是理想的. 例如,分两个步骤执行任务,以提高工作效率,可以使用多线程技术打开两个线程,第一个线程是第一步,第二个线程是第二步. 这时,要注意同步. 因为只有第一步才能完成做第二步的工作. 此时,您可以使用同步技术程之间进行通信.

根据这种情况,说明多线程之间的通信. 在Windows平台下,用于多线程之间通信的主要方法是:

(1)共享全局变量,例如上面的问题,第一步是将收据传递给第二步,可以共享全局变量,让两个线程传递数据,这时的主要考虑是变量的同步,因为当后续线程对数据进行操作时,第一个线程会更改数据的内容,并且同步没有受到保护,因此后果非常严重(即读回脏数据). 在这种情况下,考虑同步的简单方法是设置bool标志. 例如,在第二个线程用完数据之前,第一个线程无法写入. 有时,当两个线程所需的时间不相同时,如何实现最大效率的同步会更加麻烦. 此时,可以再打开几个缓冲区进行操作. 如果两个线程已在运行,则由于时间不一致,缓冲区迟早会溢出. 在这种情况下,请考虑是允许写入数据还是覆盖旧数据. 此时,应分析具体问题. 也就是说,使用bool变量控制同步,Linux和Windows相同.

类似于上面的问题,共享全局变量同步问题. 除了使用布尔变量外,还有互斥体. 那是锁定的. 在Windows下锁定类似于在Linux下锁定. 互斥锁用于同步. 要输入该代码,必须首先获取互斥体.

在Windows下的互斥锁的功能是: createmutex()创建一个互斥锁,然后获取互斥锁waitforsingleobject()函数,并在其用尽时释放互斥锁ReleaseMutex(hMutex),当其减小为0时,内核仅释放其对象. 以下是Windows下相互排斥的几个函数原型.

HANDLE WINAPI CreateMutex(

__ in LPSECURITY_ATTRIBUTES lpMutexAttributes

__在BOOL bInitialOwner中,

__在LPCTSTR lpName中

);

可用于创建已命名或未命名的互斥对象

第一个参数可以指向结构SECURITY_ATTRIBUTES通常可以设置为null;

第二个参数是指当时的功能对于当前所有者而言是否处于归纳状态FALSE不会创建互斥

第三个参数指示它是否是众所周知的互斥对象. 如果未命名,则使用null.

DWORD WINAPI WaitForSingleObject(

__在HANDLE hHandle中,

__ in DWORD dwMilliseconds

);

第一个是创建的互斥锁的句柄. 第二个是将其设置为INFINITE宏后将返回的时间,直到用户定义返回值,它才会返回.

对于linux操作系统,互斥是相似的,只是功能不同. 在Linux下,与互斥有关的几个功能:

pthread_mutex_init函数: 初始化互斥锁;

pthread_mutex_destroy函数: 取消互斥锁;

pthread_mutex_lock函数: 锁定,如果失败,则阻塞并等待;

pthread_mutex_unlock函数: 解锁;

pthread_mutex_trylock函数: 测试锁定,如果失败,则立即返回,错误代码为EBUSY;

关于这些功能的用法,我在这里不会多谈. Windows下还有一种方法可以用来保护数据,它也是线程同步的方法

这是关键部分. 关键部分类似于互斥. 它们之间的区别是关键部分很快,但是它只能用于同步同一进程中的多个线程. 关键区域的获取和释放功能如下:

EnterCriticalSection()进入关键部分; LeaveCriticalSection()离开关键部分.

(2)消息机制用于多线程通信和同步. Windows下的消息机制功能主要用于后消息.

(3)Windows下的另一种线程通信方法是事件和信号量. 同样对于开头给出的示例,两个线程是同步的,并且信息在它们之间传递. 可以使用事件或信号量. 例如,第一个线程完成生产数据后,必须告诉第二个线程,他已经准备好数据,您可以将其拿走. 第二个线程获取数据. 在这里您可以使用消息机制. 当第一个线程准备好数据时,您可以直接将消息发送到第二个线程. 使用postmessage一个线程来解决此问题是合乎逻辑的.

对于linux,有一种类似的方法,即条件变量,其中Windows和linux不同.

对于Windows,使用事件和信号同步时,将使用waitforsingleobject()进行等待. 该函数的第一个参数是一个句柄,它可以是事件句柄或信号量句柄. 第二个参数是waiting延迟,到底要等待多长时间,单位为ms,如果此参数为INFINITE,则它无限期地等待. 释放信号量的函数是ReleaseSemaphore();释放事件的函数是SetEvent. 使用这些东西进行初始化.

对于linux操作系统,条件变量用于实现类似的功能. Linux的条件变量通常与互斥锁一起使用. 主要功能是:

pthread_mutex_lock

pthread_mutex_unlock,

pthread_cond_init

linux的进程与线程_linux 线程 pthread_create_linux用不了多线程

pthread_cond_signal

pthread_cond_wait

pthread_cond_timewait

要与Windows操作系统进行比较,请使用下表进行比较:

与上表比较,总结如下:

(1)Pthread_cleanup_push,Pthread_cleanup_pop:

这对函数push和pop的作用是在异常退出发生时执行一些清除操作,也就是说,当push和pop函数之间的异常退出(包括调用pthread_exit退出)时,push中的清除函数将如果有多次推入,则执行该命令,注意堆栈,先执行后一个函数,然后执行前一个函数,但请注意,当通过返回这两个函数之间的命令退出时,未执行推入的函数将查看弹出功能该参数不再为0. 另外,在没有异常退出的情况下,与返回退出的情况相同,即当弹出功能参数不为0时,执行清除操作,当弹出功能参数为0时,将执行清除功能. 推送功能未执行.

(2)pthread_cond_signal与Linux的SetEvent之间的区别

Pthread_cond_singal释放信号后,如果没有Pthread_cond_wait,则立即重置信号. 这与SetEvent不同,并且SetEvent不会重置. 详细说明如下:

有2种常见的模型用于设置和重置条件变量: 第一个模型是设置条件变量(带信号)时linux用不了多线程,如果当前没有线程正在等待,则其状态将保持设置(带信号),而状态不会更改为无信号,直到触发等待线程条目. 该模型由Windows平台上的自动设置事件表示.

第二个模型是pthread在Linux平台上使用的模型. 条件变量设置(带信号)后,即使当前没有线程在等待,其状态也将返回无符号状态.

在Linux平台上这种条件变量模型很难说. 在实际应用中,可以略微改进代码以避免这种差异. 由于这种差异仅在触发器不等待线程的条件变量时发生,因此仅需掌握触发器的时间即可. 最简单的方法是增加一个计数器,以记录等待线程的数量,并在决定触发条件变量之前检查该变量.

示例

使用pthread_cond_wait()和pthread_cond_signal()

pthread_mutex_t count_lock;

pthread_cond_t count_nonzero;

无符号数;

decrement_count()

{

pthread_mutex_lock(&count_lock);

同时(计数== 0)

pthread_cond_wait(&count_nonzero,&count_lock);

count = count-1;

pthread_mutex_unlock(&count_lock);

}

increment_count()

{

pthread_mutex_lock(&count_lock);

如果(计数== 0)

pthread_cond_signal(&count_nonzero);

count = count + 1;

pthread_mutex_unlock(&count_lock);

}

(3)当Pthread_cond_wait条件返回时,请注意互斥锁的解锁

extern int pthread_cond_wait __P((pthread_cond_t * __ cond,pthread_mutex_t * __ mutex));

调用此函数时,线程将解锁互斥锁所指向的锁,并被条件变量cond阻止. 可以通过函数pthread_cond_signal和函数pthread_cond_broadcast唤醒线程. 唤醒后,它将重新检查以查看是否满足条件. 如果不满意,通常该线程仍应在此处被阻塞,等待下一次唤醒. 如果使用pthread_cond_wait等待多线程处理,则互斥量将首先释放. 当等待信号到达时,将再次获得互斥锁,因此之后必须注意手动解锁. 示例如下:

#include

#include

#include

pthread_mutex_t互斥锁= PTHREAD_MUTEX_INITIALIZER; / *初始化互斥锁* /

linux用不了多线程_linux 线程 pthread_create_linux的进程与线程

pthread_cond_t cond = PTHREAD_COND_INITIALIZER; //初始化条件变量

void * thread1(void *);

void * thread2(void *);

int i = 1;

int main(void)

{

pthread_t t_a;

pthread_t t_b;

pthread_create(&t_a,NULL,thread1,(void *)NULL); / *创建进程t_a * /

pthread_create(&t_b,NULL,thread2,(void *)NULL); / *创建进程t_b * /

pthread_join(t_b,NULL); / *等待进程t_b结束* /

pthread_mutex_destroy(&mutex);

pthread_cond_destroy(&cond);

exit(0);

}

无效* thread1(无效*垃圾)

{

for(i = 1; i <= 9; i ++)

{

printf(“ IN one \ n”);

pthread_mutex_lock(&mutex); //

if(i%3 == 0)

pthread_cond_signal(&cond); / *,发送信号通知t_b进程* /

其他

printf(“ thead1: %d \ n”,i);

pthread_mutex_unlock(&mutex); // *解锁互斥锁* /

printf(“ Up Mutex \ n”);

sleep(3);

}

}

无效* thread2(无效*垃圾)

{

while(i <9)

{

printf(“在两个\ n”);

pthread_mutex_lock(&mutex);

if(i%3!= 0)

pthread_cond_wait(&cond,&mutex); / *等待* /

printf(“ thread2: %d \ n”,i);

pthread_mutex_unlock(&mutex);

printf(“ Down Mutex \ n”);

linux用不了多线程_linux 线程 pthread_create_linux的进程与线程

sleep(3);

}

}

输出如下:

合一

thead1: 1

互斥量

一分为二

合一

thead1: 2

互斥量

合一

thread2: 3

互斥体下

互斥量

合一

thead1: 4

互斥量

一分为二

合一

thead1: 5

互斥量

合一

互斥量

thread2: 6

互斥体下

一分为二

thread2: 6

互斥体下

合一

thead1: 7

互斥量

合一

thead1: 8

互斥量

一分为二

合一

互斥量

thread2: 9

互斥体下

请注意,蓝色有2个线程2: 6. 实际上,当该程序执行多次时,i = 3和i = 6可能会打印更多内容. 这是由于竞争锁定造成的.

linux 线程 pthread_create_linux用不了多线程_linux的进程与线程

(4)要注意的另一件事是Pthread_cond_timedwait等待绝对时间. 这与WaitForSingleObject不同. 互联网上也讨论了Pthread_cond_timedwait. 如下:

thread_a:

pthread_mutex_lock(&mutex);

//做点事情

pthread_mutex_unlock(&mutex)

thread_b:

pthread_mutex_lock(&mutex);

//做点事情

pthread_cond_timedwait(&cond,&mutex,&tm);

pthread_mutex_unlock(&mutex)

上面有两个线程thread_a,thread_b. 现在,如果a已进入临界区并且b同时超时,那么b是否将从pthread_cond_timedwait返回?如果可以返回,不是a和b都在关键部分吗?如果您无法返回,pthread_cond_timedwait的时间安排是否错误?

每个人都讨论了以下两个有价值的观点:

(1)pthread_cond_timedwait(pthread_cond_t * cv,pthread_mutex_t * external_mutex,const struct timespec * abstime)-此函数是pthread_cond_wait的基于时间的变体. 它会等待最长时间以通知cv. 如果在通知cv之前已经过了abstime,则该函数将以ETIME结果返回给调用者,表明发生了超时. 即使在超时的情况下,当pthread_cond_timedwait返回时,external_mutex也将被锁定.

(2)2.1 pthread_cond_timedwait的行为与pthread_cond_wait相同,返回时必须再次锁定互斥锁.

2. 2pthread_cond_timed等待所谓的return,如果它不等待条件变量,则不准确.

如果pthread_cond_timedwait超时,但此时关键部分无法锁定,则pthread_cond_timedwait不会立即返回,但是当pthread_cond_timedwait返回时,它仍位于关键部分中,此时的返回值为ETIMEDOUT.

对于pthread_cond_timedwait返回加班的问题,我也同意意见2.

附录:

int pthread_create(pthread_t *限制tidp,const pthread_attr_t * restrict_attr,void *(* start_rtn)(void *),void * restrict arg);

返回值: 如果成功,则返回0,否则返回错误号

返回成功时,将tidp指向的存储单元设置为新创建的线程的线程ID. attr参数用于制定各种线程属性. 新创建的线程从start_rtn函数的地址开始. 此函数只有一个无指针参数arg. 如果需要将多个参数传递给start_rtn函数,则需要将这些参数放入一个结构中,然后使用该结构的地址作为arg的参数.

C用于在Linux下开发多线程程序. Linux系统下的多线程遵循POSIX线程接口,称为pthreads.

装饰有限制的指针是最初访问该指针所指向的对象的唯一方法. 仅当第二个指针基于第一个指针时,才可以访问该对象. 对对象的访问仅限于由strict修改的指针表达式. 使用strict装饰的指针主要用于函数参数或指向由malloc()分配的内存空间. 限制数据类型不会更改程序的语义. 通过假设限制修改的指针是访问对象的唯一方法,编译器可以更好地优化某些类型的例程.

第一个参数是指向线程标识符的指针.

第二个参数用于设置线程属性.

第三个参数是线程运行函数的起始地址.

第四个参数是运行函数的参数.

由于pthread不是linux系统库,因此在编译时调用静态链接库时请注意添加-lpthread参数.

终止线程:

如果您在进程中的任何线程中调用exit或_exit,整个过程将终止,并且该线程的常规退出方法为:

(1)线程从启动例程返回(返回)

(2)线程可以被另一个进程杀死;

(3)线程自己调用pthread_exit函数

#include

pthread_exit

线程等待:

int pthread_join(pthread_t tid,void ** rval_ptr)

函数pthread_join用于等待线程结束. 函数原型为:

extern int pthread_join __P(pthread_t __th,void ** __ thread_return);

第一个参数是等待线程的标识符,第二个参数是用户定义的指针,可用于存储等待线程的返回值. 该功能是线程阻塞功能. 调用它的函数将等待,直到等待线程结束. 函数返回后,将恢复等待线程的资源.

从开源中文社区转移而来linux用不了多线程,其内容已被修改:


本文来自电脑杂谈,转载请注明本文网址:
https://www.pc-fly.com/a/jisuanjixue/article-254880-1.html

    相关阅读
      发表评论  请自觉遵守互联网相关的政策法规,严禁发布、暴力、反动的言论

      热点图片
      拼命载入中...