
这是一个多线程例子,里面只有两个线程,是生产者/消费者模式,已编译通过,注释很详细,
如下:
/ 以生产者和消费者模型问题来阐述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语言如何编写一个简单的多线程程序、程序开发中如何将线程让出来、易语言启动线程()用法等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)