c语言如何编写一个简单的多线程程序

c语言如何编写一个简单的多线程程序,第1张

这是一个多线程例子,里面只有两个线程,是生产者/消费者模式,已编译通过,注释很详细,

如下:

/ 以生产者和消费者模型问题来阐述Linux线程的控制和通信你

生产者线程将生产的产品送入缓冲区,消费者线程则从中取出产品。

缓冲区有N个,是一个环形的缓冲池。

/

#include <stdioh>

#include <pthreadh>

#define BUFFER_SIZE 16

struct prodcons

{

int buffer[BUFFER_SIZE];/实际存放数据的数组/

pthread_mutex_t lock;/互斥体lock,用于对缓冲区的互斥 *** 作/

int readpos,writepos; /读写指针/

pthread_cond_t notempty;/缓冲区非空的条件变量/

pthread_cond_t notfull;/缓冲区未满 的条件变量/

};

/初始化缓冲区/

void pthread_init( struct prodcons p)

{

pthread_mutex_init(&p->lock,NULL);

pthread_cond_init(&p->notempty,NULL);

pthread_cond_init(&p->notfull,NULL);

p->readpos = 0;

p->writepos = 0;

}

/将产品放入缓冲区,这里是存入一个整数/

void put(struct prodcons p,int data)

{

pthread_mutex_lock(&p->lock);

/等待缓冲区未满/

if((p->writepos +1)%BUFFER_SIZE ==p->readpos)

{

pthread_cond_wait(&p->notfull,&p->lock);

}

p->buffer[p->writepos] =data;

p->writepos++;

if(p->writepos >= BUFFER_SIZE)

p->writepos = 0;

pthread_cond_signal(&p->notempty);

pthread_mutex_unlock(&p->lock);

}

/从缓冲区取出整数/

int get(struct prodcons p)

{

int data;

pthread_mutex_lock(&p->lock);

/等待缓冲区非空/

if(p->writepos == p->readpos)

{

pthread_cond_wait(&p->notempty ,&p->lock);//非空就设置条件变量notempty

}

/读书据,移动读指针/

data = p->buffer[p->readpos];

p->readpos++;

if(p->readpos == BUFFER_SIZE)

p->readpos = 0;

/设置缓冲区未满的条件变量/

pthread_cond_signal(&p->notfull);

pthread_mutex_unlock(&p->lock);

return data;

}

/测试:生产站线程将1 到1000的整数送入缓冲区,消费者线程从缓冲区中获取整数,两者都打印信息/

#define OVER (-1)

struct prodcons buffer;

void producer(void data)

{

int n;

for( n=0;n<1000;n++)

{

printf("%d ------>\n",n);

put(&buffer,n);

}

put(&buffer,OVER);

return NULL;

}

void consumer(void data)

{

int d;

while(1)

{

d = get(&buffer);

if(d == OVER)

break;

else

printf("----->%d\n",d);

}

return NULL;

}

int main()

{

pthread_t th_p,th_c;

void retval;

pthread_init(&buffer);

pthread_create(&th_p,NULL,producer,0);

pthread_create(&th_c,NULL,consumer,0);

/等待两个线程结束/

pthread_join(th_p, &retval);

pthread_join(th_c,&retval);

return 0;

}

让出处理就是把一个协程让出来的意思。

1Lu a 内部使用 C 的 longjmp 机制让出一个协程。 因此,如果一个 C 函数 foo 调用了一个 API 函数, 而这个 API 函数让出了(直接或间接调用了让出函数)。 由于 longjmp 会移除 C 栈的栈帧, Lu a 就无法返回到 foo 里了。

2为了回避这类问题, 碰到 API 调用中调用让出时,除了那些抛出错误的 API 外,还提供了三个函数: lua_yieldk, lua_callk,和 lua_pcallk 。 它们在让出发生时,可以从传入的 延续函数 (名为 k 的参数)继续运行。

3我们需要预设一些术语来解释延续点。 对于从 Lua 中调用的 C 函数,我们称之为 原函数。 从这个原函数中调用的上面所述的三个 C API 函数我们称之为 被调函数。 被调函数可以使当前线程让出。 (让出发生在被调函数是 lua_yieldk, 或传入 lua_callk 或 lua_pcallk 的函数调用了让出时。)

4假设正在运行的线程在执行被调函数时让出。 当再次延续这条线程,它希望继续被调函数的运行。 然而,被调函数不可能返回到原函数中。 这是因为之前的让出 *** 作破坏了 C 栈的栈帧。 作为替代品,Lu a 调用那个作为被调函数参数给出的 延续函数 。 正如其名,延续函数将延续原函数的任务。

5注意这里那个额外的显式的对延续函数的调用: L ua 仅在需要时,这可能是由错误导致的也可能是发生了让出而需要继续运行,才会调用延续函数。 如果没有发生过任何让出,调用的函数正常返回, 那么 lua_pcallk (以及 lua_callk)也会正常返回。 (当然,这个例子中你也可以不在之后调用延续函数, 而是在原函数的调用后直接写上需要做的工作。)

6L ua 会把延续函数看作原函数。 延续函数将接收到和原函数相同的 L ua 栈,其接收到的 lua 状态也和 被调函数若返回后应该有的状态一致。 (例如, lua_callk 调用之后, 栈中之前压入的函数和调用参数都被调用产生的返回值所替代。) 这时也有相同的上值。 等到它返回的时候,Lua 会将其看待成原函数的返回去 *** 作。

启动线程可以将子程序赋值给第一个参数,强制结束线程可以将启动线程返回的句柄赋值给第一个参数。

1、新建易语言程序,在启动窗口上添加一个按钮,然后双击这个按钮进入代码区域:

2、进入代码区域后,右击代码区域空白部分,在展开的菜单中点击“新子程序”按钮创建一个新的子程序:

3、创建子程序后,使用启动线程命令,第一个参数为“&”+子程序名,然后将第三个参数返回给一个变量:

4、如果需要结束线程,可以用强制结束线程命令,参数为启动线程返回的句柄,这时可以将线程强制关闭:

1、程序建立1000个线程,有可能造成系统创建大量线程而导致消耗完系统内存,还会增加创建和销毁线程上所花的时间以及系统资源的开销

2、在创建线程数多的情况下,可以考虑使用线程池

以下是Java自带的几种线程池:

(1)、newFixedThreadPool 创建一个指定工作线程数量的线程池。

每当提交一个任务就创建一个工作线程,如果工作线程数量达到线程池初始的最大数,则将提交的任务存入到池队列中。

(2)、newCachedThreadPool 创建一个可缓存的线程池。

这种类型的线程池特点是:

1)工作线程的创建数量几乎没有限制(其实也有限制的,数目为Interger MAX_VALUE), 这样可灵活的往线程池中添加线程。

2)如果长时间没有往线程池中提交任务,即如果工作线程空闲了指定的时间(默认为1分钟),则该工作线程将自动终止。终止后,如果你又提交了新的任务,则线程池重新创建一个工作线程。

(3)、newSingleThreadExecutor 创建一个单线程化的Executor,即只创建唯一的工作者线程来执行任务,如果这个线程异常结束,会有另一个取代它,保证顺序执行(我觉得这点是它的特色)。

单工作线程最大的特点是可保证顺序地执行各个任务,并且在任意给定的时间不会有多个线程是活动的 。

(4)、newScheduleThreadPool 创建一个定长的线程池,而且支持定时的以及周期性的任务执行,类似于Timer。

3、示例代码

package test;  

import javautilconcurrentExecutorService;  

import javautilconcurrentExecutors;  

public class ThreadPoolExecutorTest {  

 public static void main(String[] args) {  

  ExecutorService cachedThreadPool = ExecutorsnewCachedThreadPool();  

  for (int i = 0; i < 1000; i++) {  

   

   cachedThreadPoolexecute(new Runnable() {  

    public void run() {  

         //在这里执行你需要的功能

    }  

   });  

  }  

 }  

}

DWORD CChatDlg::RecvProc(void)

{

return 0;

}

这里错了,你的线程函数的返回值应该是 DWORD WINAPI 。。

在函数声明和定义的时候都要改

以上就是关于c语言如何编写一个简单的多线程程序全部的内容,包括:c语言如何编写一个简单的多线程程序、程序开发中如何将线程让出来、易语言启动线程()用法等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/zz/9630909.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-04-30
下一篇2023-04-30

发表评论

登录后才能评论

评论列表(0条)

    保存