C多线程编程实例实战
- 格式:docx
- 大小:840.80 KB
- 文档页数:3
c++多线程实现方法C++是一种强大的编程语言,其在多线程编程方面表现出色。
为了实现多线程,需要使用C++中的线程库。
下面是C++多线程实现方法的详细介绍。
1. 创建线程要创建一个线程,需要使用C++中的thread类。
创建线程的基本语法如下:```#include <thread>void myFunction(){// do something}int main(){std::thread t(myFunction); // 创建线程t.join(); // 等待线程结束return 0;}```2. 传递参数如果需要向线程传递参数,可以通过将参数传递给线程构造函数来实现。
```#include <thread>void myFunction(int x){// do something with x}int main(){int x = 42;std::thread t(myFunction, x); // 向线程传递参数t.join(); // 等待线程结束return 0;}```3. 多线程同步在多线程编程中,同步是一项重要的任务。
C++中提供了多种同步机制,如互斥锁和条件变量。
互斥锁是一种保护共享资源的机制。
在访问共享资源之前,线程必须获取互斥锁。
在完成操作后,线程必须释放互斥锁,以便其他线程可以访问共享资源。
```#include <mutex>std::mutex myMutex; // 定义互斥锁void myFunction(){myMutex.lock(); // 获取互斥锁// do something with shared resourcemyMutex.unlock(); // 释放互斥锁}int main(){std::thread t1(myFunction);std::thread t2(myFunction);t1.join();t2.join();return 0;}```条件变量是一种允许线程在特定条件下等待的机制。
C#多线程编程实战(⼀):线程基础1.1 简介为了防⽌⼀个应⽤程序控制CPU⽽导致其他应⽤程序和操作系统本⾝永远被挂起这⼀可能情况,操作系统不得不使⽤某种⽅式将物理计算分割为⼀些虚拟的进程,并给予每个执⾏程序⼀定量的计算能⼒。
此外操作系统必须始终能够优先访问CPU,并能调整不同程序访问CPU的优先级。
线程正式这⼀慨念的实现。
多线程优点:可以同时执⾏多个计算任务,有可能提⾼计算机的处理能⼒,使得计算机每秒能执⾏越来越多的命令多线程缺点:消耗⼤量的操作系统资源。
多个线程共享⼀个处理器将导致操作系统忙于管理这些线程,⽽⽆法运⾏程序。
1.2 创建线程using System;using System.Threading;namespace MulityThreadNote{class Program{static void Main(string[] args){Thread t1 = new Thread(new ThreadStart(PrintNumbers));//⽆参数的委托t1.Start();Thread t2 = new Thread(new ParameterizedThreadStart(PrintNumbers));//有参数的委托t2.Start(10);Console.ReadLine();}static void PrintNumbers(){Console.WriteLine("Starting...");for (int i = 0; i < 10; i++){Console.WriteLine(i);}}//注意:要使⽤ParameterizedThreadStart,定义的参数必须为objectstatic void PrintNumbers(object count){Console.WriteLine("Starting...");for (int i = 0; i < Convert.ToInt32(count); i++){Console.WriteLine(i);}}}}注释:我们只需指定在不同线程运⾏的⽅法名,⽽C#编译器会在后台创建这些对象1.3 暂停线程using System;using System.Threading;namespace MulityThreadNote{class Program{static void Main(string[] args){Thread t1 = new Thread(PrintNumbersWithDelay);t1.Start();PrintNumbers();Console.ReadLine();}static void PrintNumbers(){Console.WriteLine("Starting...");for (int i = 0; i < 10; i++){Console.WriteLine(i);}}static void PrintNumbersWithDelay(){Console.WriteLine("Starting...");for (int i = 0; i < 10; i++){Thread.Sleep(TimeSpan.FromSeconds(2));Console.WriteLine(i);}}}}注释:使⽤Thread.Sleep(TimeSpan.FromSeconds(2));暂停线程1.4 线程等待using System;namespace MulityThreadNote{class Program{static void Main(string[] args){Console.WriteLine("Starting...");Thread t = new Thread(PrintNumbersWithDelay);t.Start();t.Join(); //使⽤Join等待t完成PrintNumbers();Console.WriteLine("THread Complete");Console.ReadLine();}static void PrintNumbers(){Console.WriteLine("Starting...");for (int i = 0; i < 10; i++){Console.WriteLine(i);}}static void PrintNumbersWithDelay(){Console.WriteLine("Starting...");for (int i = 0; i < 10; i++){Thread.Sleep(TimeSpan.FromSeconds(2));Console.WriteLine(i);}}}}注释:使⽤t.Join(); 等待t完成1.5 终⽌线程using System;using System.Threading;namespace MulityThreadNote{class Program{static void Main(string[] args){Console.WriteLine("Starting Program...");Thread t1 = new Thread(PrintNumbersWithDelay);t1.Start();Thread.Sleep(TimeSpan.FromSeconds(6));t1.Abort(); //使⽤Abort()终⽌线程Console.WriteLine("Thread t1 has been aborted");Thread t2 = new Thread(PrintNumbers);PrintNumbers();Console.ReadLine();}static void PrintNumbers(){Console.WriteLine("Starting...");for (int i = 0; i < 10; i++){Console.WriteLine(i);}}static void PrintNumbersWithDelay(){Console.WriteLine("Starting...");for (int i = 0; i < 10; i++){Thread.Sleep(TimeSpan.FromSeconds(2));Console.WriteLine(i);}}}}注释:使⽤Thread实例的Abort⽅法终⽌线程1.6 检测线程状态using System;using System.Threading;namespace MulityThreadNote{class Program{static void Main(string[] args){Console.WriteLine("Start Program...");Thread t1 = new Thread(PrintNumbersWithStatus);Thread t2 = new Thread(DoNothing);Console.WriteLine(t1.ThreadState.ToString());//获取实例线程状态 t2.Start();t1.Start();for (int i = 0; i < 30; i++)}Thread.Sleep(TimeSpan.FromSeconds(6));t1.Abort();Console.WriteLine("thread t1 has been aborted");Console.WriteLine(t1.ThreadState.ToString());Console.WriteLine(t2.ThreadState.ToString());Console.ReadLine();}private static void PrintNumbersWithStatus(){Console.WriteLine("Starting...");Console.WriteLine(Thread.CurrentThread.ThreadState.ToString());//获取当前线程状态for (int i = 0; i < 10; i++){Thread.Sleep(TimeSpan.FromSeconds(2));Console.WriteLine(i);}}private static void DoNothing(){Thread.Sleep(TimeSpan.FromSeconds(2));}}}注释:使⽤Thread.ThreadState获取线程的运⾏状态。
第1篇一、实验目的1. 理解多线程的概念和作用。
2. 掌握多线程的创建、同步和通信方法。
3. 熟悉Java中多线程的实现方式。
4. 提高程序设计能力和实际应用能力。
二、实验环境1. 操作系统:Windows 102. 开发工具:IntelliJ IDEA3. 编程语言:Java三、实验内容本次实验主要完成以下任务:1. 创建多线程程序,实现两个线程分别执行不同的任务。
2. 使用同步方法实现线程间的同步。
3. 使用线程通信机制实现线程间的协作。
四、实验步骤1. 创建两个线程类,分别为Thread1和Thread2。
```javapublic class Thread1 extends Thread {@Overridepublic void run() {// 执行Thread1的任务for (int i = 0; i < 10; i++) {System.out.println("Thread1: " + i);}}}public class Thread2 extends Thread {@Overridepublic void run() {// 执行Thread2的任务for (int i = 0; i < 10; i++) {System.out.println("Thread2: " + i);}}}```2. 创建一个主类,在主类中创建两个线程对象,并启动它们。
```javapublic class Main {public static void main(String[] args) {Thread thread1 = new Thread1();Thread thread2 = new Thread2();thread1.start();thread2.start();}```3. 使用同步方法实现线程间的同步。
```javapublic class SynchronizedThread extends Thread {private static int count = 0;@Overridepublic void run() {for (int i = 0; i < 10; i++) {synchronized (SynchronizedThread.class) {count++;System.out.println(Thread.currentThread().getName() + ": " + count);}}}}public class Main {public static void main(String[] args) {Thread thread1 = new SynchronizedThread();Thread thread2 = new SynchronizedThread();thread1.start();thread2.start();}```4. 使用线程通信机制实现线程间的协作。
C#多线程编程之锁的使用【互斥锁(lock )和读写锁(ReadWriteLock )】今天主要介绍下C#的两种锁:互斥锁(lock)和读写锁(ReadWriteLock)互斥锁(lock)lock 关键字将语句块标记为临界区,方法是获取给定对象的互斥锁,执行语句,然后释放该锁。
当任何一个线程获取到锁后,其他线程如果需要使用该临界区内代码,则必须等待前一个线程使用完毕后释放锁。
代码示例:12345 Object thisLock = new Object(); lock (thisLock) { // 临界区代码块 }读写锁(ReadWriteLock)ReadWriteLock 定义支持单个写线程和多个读线程的锁。
该锁的作用主要是解决并发读的性能问题,使用该锁,可以大大提高数据并发访问的性能,只有在写时,才会阻塞所有的读锁。
示例代码:1 2 3 4 5 6 7 8 9 10 11 1using System.Collections.Generic;using System.Windows;using System.Threading;namespace FYSTest{public partial class MainWindow : Window{List<int> list = new List<int>();private ReaderWriterLock _rwlock= new ReaderWriterLock();public MainWindow()2 13 14 15 16 17 18 19 2 0 2 1 2 2 2 3 2 4 2 5 2 6 2 7 2 8 2 9 3 0 3 1 3 2 3 3 3{InitializeComponent();Thread ThRead = new Thread(newThreadStart(Read));ThRead.IsBackground = true;Thread ThRead2 = new Thread(new ThreadStart(Read));ThRead2.IsBackground = true;Thread ThWrite = new Thread(new ThreadStart(Write));ThWrite.IsBackground = true;ThRead.Start();ThRead2.Start();ThWrite.Start();}private void Read(){while (true){//使用一个System.Int32 超时值获取读线程锁。
vc++2019 多线程编程例子当你在Visual Studio 2019中使用C++进行多线程编程时,你可以使用C++11标准中引入的`<thread>` 头文件来创建和管理线程。
以下是一个简单的例子,演示如何在VC++2019中使用多线程:```cpp#include <iostream>#include <thread>// 函数,将在新线程中运行void threadFunction(int id) {std::cout << "Thread " << id << " is running.\n";}int main() {// 启动三个线程std::thread t1(threadFunction, 1);std::thread t2(threadFunction, 2);std::thread t3(threadFunction, 3);// 等待线程完成t1.join();t2.join();t3.join();std::cout << "All threads have completed.\n";return 0;}```在这个例子中,`threadFunction` 函数将在新线程中运行,并且`main` 函数启动了三个不同的线程。
使用`join` 来等待线程的完成。
请确保在项目属性中的C++ 语言标准设置为C++11 或更高版本,以便支持`<thread>` 头文件。
在Visual Studio中,你可以通过右键单击项目,选择"属性",然后在"C/C++" -> "语言" 中设置"C++ 语言标准"。
记得在多线程编程中要小心处理共享资源,以避免竞态条件和其他并发问题。
多线程在Visual C#网络编程中的应用(1)一.简介在Visual C#中创建和使用线程:Visual C#中使用的线程都是通过自命名空间System.Threading中的Thread类经常实例化完成的。
通过Thread类的构造函数来创建可供Visual C#使用的线程,通过Thread中的方法和属性来设定线程属性和控制线程的状态。
以下Thread类中的最典型的构造函数语法,在Visual C#中一般使用这个构造函数来创建、初始化Thread实例。
public Thread (ThreadStartstart) ;参数start ThreadStart 委托,它将引用此线程开始执行时要调用的方法。
Thread还提供了其他的构造函数来创建线程,这里就不一一介绍了。
表01是Thread类中的一些常用的方法及其简要说明:方法说明调用此方法通常会终止线程,但会引起ThreadAbortException类Abort型异常。
Interrup中断处于WaitSleepJoin 线程状态的线程。
tJoin 阻塞调用线程,直到某个线程终止时为止。
ResetAbo取消当前线程调用的Abor方法。
rtResume 继续已挂起的线程。
Sleep 当前线程阻塞指定的毫秒数。
Start 操作系统将当前实例的状态更改为ThreadState.Running。
Suspend 挂起线程,或者如果线程已挂起,则不起作用。
表01:Thread类的常用方法及其说明这里要注意的是在.Net中执行一个线程,当线程执行完毕后,一般会自动销毁。
如果线程没有自动销毁可通过Thread中的Abort方法来手动销毁,但同样要注意的是如果线程中使用的资源没有完全销毁,Abort方法执行后,也不能保证线程被销毁。
在Thread类中还提供了一些属性用以设定和获取创建的Thread实例属性,表02中是Thread类的一些常用属性及其说明:属性说明CurrentCultu获取或设置当前线程的区域性。
C#实现多线程的同步⽅法详解本⽂主要描述在C#中线程同步的⽅法。
线程的基本概念⽹上资料也很多就不再赘述了。
直接接⼊主题,在多线程开发的应⽤中,线程同步是不可避免的。
在.Net框架中,实现线程同步主要通过以下的⼏种⽅式来实现,在MSDN的线程指南中已经讲了⼏种,本⽂结合作者实际中⽤到的⽅式⼀起说明⼀下。
1. 维护⾃由锁(InterLocked)实现同步2. 监视器(Monitor)和互斥锁(lock)3. 读写锁(ReadWriteLock)4. 系统内核对象1) 互斥(Mutex), 信号量(Semaphore), 事件(AutoResetEvent/ManualResetEvent)2) 线程池除了以上的这些对象之外实现线程同步的还可以使⽤Thread.Join⽅法。
这种⽅法⽐较简单,当你在第⼀个线程运⾏时想等待第⼆个线程执⾏结果,那么你可以让第⼆个线程Join进来就可以了。
⾃由锁(InterLocked)对⼀个32位的整型数进⾏递增和递减操作来实现锁,有⼈会问为什么不⽤++或--来操作。
因为在多线程中对锁进⾏操作必须是原⼦的,⽽++和--不具备这个能⼒。
InterLocked类还提供了两个另外的函数Exchange, CompareExchange⽤于实现交换和⽐较交换。
Exchange操作会将新值设置到变量中并返回变量的原来值: int oVal = InterLocked.Exchange(ref val, 1)。
监视器(Monitor)在MSDN中对Monitor的描述是: Monitor 类通过向单个线程授予对象锁来控制对对象的访问。
Monitor类是⼀个静态类因此你不能通过实例化来得到类的对象。
Monitor 的成员可以查看MSDN,基本上Monitor的效果和lock是⼀样的,通过加锁操作Enter设置临界区,完成操作后使⽤Exit操作来释放对象锁。
不过相对来说Monitor的功能更强,Moniter可以进⾏测试锁的状态,因此你可以控制对临界区的访问选择,等待or离开, ⽽且Monitor还可以在释放锁之前通知指定的对象,更重要的是使⽤Monitor可以跨越⽅法来操作。
c语言程序设计案例
以下是一个简单的 C 语言程序设计案例:
```c
#include <stdio.h>
int main() {
int num1, num2, sum;
printf("请输入两个整数:
");
scanf("%d%d", &num1, &num2);
sum = num1 + num2;
printf("两数之和为:%d
", sum);
return 0;
}
```
该程序通过两个输入框,让用户分别输入两个整数,然后计算它们的和,并将结果输出到屏幕上。
具体实现过程如下:
1. 首先包含头文件 `stdio.h`,该头文件提供了标准输入输出函数的支持。
2. 定义三个整数变量 `num1`、`num2` 和 `sum`,分别用于存储输入的第一个整数、第二个整数和两个整数的和。
3. 通过 `scanf()` 函数获取两个整数的输入值,并将输入的值存储到 `num1` 和 `num2` 变量中。
4. 计算两个整数的和,将其存储在 `sum` 变量中。
5. 通过 `printf()` 函数输出两数之和的结果到屏幕上。
在程序运行时,用户可以通过输入框分别输入两个整数,然后运行该程序,程序将会输出两数之和的结果。
linux下的CC++多进程多线程编程实例详解linux下的C\C++多进程多线程编程实例详解1、多进程编程#include <stdlib.h>#include <sys/types.h>#include <unistd.h>int main(){pid_t child_pid;/* 创建⼀个⼦进程 */child_pid = fork();if(child_pid == 0){printf("child pid\n");exit(0);}else{printf("father pid\n");sleep(60);}return 0;}2、多线程编程#include <stdio.h>#include <pthread.h>struct char_print_params{char character;int count;};void *char_print(void *parameters){struct char_print_params *p = (struct char_print_params *)parameters;int i;for(i = 0; i < p->count; i++){fputc(p->character,stderr);}return NULL;}int main(){pthread_t thread1_id;pthread_t thread2_id;struct char_print_params thread1_args;struct char_print_params thread2_args;thread1_args.character = 'x';thread1_args.count = 3000;pthread_create(&thread1_id, NULL, &char_print, &thread1_args);thread2_args.character = 'o';thread2_args.count = 2000;pthread_create(&thread2_id, NULL, &char_print, &thread2_args);pthread_join(thread1_id, NULL);pthread_join(thread2_id, NULL);return 0;}3、线程同步与互斥1)、互斥pthread_mutex_t mutex;pthread_mutex_init(&mutex, NULL);/*也可以⽤下⾯的⽅式初始化*/pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_lock(&mutex);/* 互斥 */thread_flag = value;pthread_mutex_unlock(&mutex);2)、条件变量int thread_flag = 0;pthread_mutex_t mutex;pthread_cond_t thread_flag_cv;\void init_flag(){pthread_mutex_init(&mutex, NULL);pthread_cond_init(&thread_flag_cv, NULL);thread_flag = 0;}void *thread_function(void *thread_flag){while(1){pthread_mutex_lock(&mutex);while(thread_flag != 0 ){pthread_cond_wait(&thread_flag_cv, &mutex);}pthread_mutex_unlock(&mutex);do_work();}return NULL;}void set_thread_flag(int flag_value){pthread_mutex_lock(&mutex);thread_flag = flag_value;pthread_cond_signal(&thread_flag_cv);pthread_mutex_unlock(&mutex);}感谢阅读,希望能帮助到⼤家,谢谢⼤家对本站的⽀持!。
c语言多线程编程实例C语言多线程编程实例多线程编程是一种并发编程的方式,它可以让程序同时执行多个任务,提高程序的效率和响应速度。
C语言是一种广泛使用的编程语言,也支持多线程编程。
本文将介绍一些C语言多线程编程的实例,帮助读者更好地理解和掌握多线程编程技术。
1. 创建线程在C语言中,可以使用pthread库来创建线程。
下面是一个简单的例子,创建一个线程并让它输出一段文字:```#include <stdio.h>#include <pthread.h>void* thread_func(void* arg){printf("Hello, world!\n");return NULL;}int main(){pthread_t tid;pthread_create(&tid, NULL, thread_func, NULL);pthread_join(tid, NULL);return 0;}```在上面的代码中,我们定义了一个函数thread_func,它将作为线程的入口函数。
在main函数中,我们使用pthread_create函数创建了一个线程,并将thread_func作为入口函数。
然后使用pthread_join 函数等待线程结束。
2. 线程同步在多线程编程中,线程之间的同步非常重要。
下面是一个例子,演示如何使用互斥锁来保护共享资源:```#include <stdio.h>#include <pthread.h>int count = 0;pthread_mutex_t mutex;void* thread_func(void* arg){pthread_mutex_lock(&mutex);count++;printf("Thread %d: count = %d\n", (int)arg, count); pthread_mutex_unlock(&mutex);return NULL;}int main(){pthread_t tid1, tid2;pthread_mutex_init(&mutex, NULL);pthread_create(&tid1, NULL, thread_func, (void*)1); pthread_create(&tid2, NULL, thread_func, (void*)2); pthread_join(tid1, NULL);pthread_join(tid2, NULL);pthread_mutex_destroy(&mutex);return 0;}```在上面的代码中,我们定义了一个全局变量count,它将被两个线程同时访问。
C#TCP 多线程服务器⽰例前⾔之前⼀直很少接触多线程这块。
这次项⽬中刚好⽤到了⽹络编程TCP 这块,做⼀个服务端,需要使⽤到多线程,所以记录下过程。
希望可以帮到⾃⼰的同时能给别⼈带来⼀点点收获~关于TCP 的介绍就不多讲,神马经典的三次握⼿、四次握⼿,可以参考下⾯⼏篇博客学习了解:效果预览客户端是⼀个门禁设备,主要是向服务端发送实时数据(200ms)。
服务端解析出进出⼈数并打印显⽰。
实现步骤因为主要是在服务器上监听各设备的连接请求以及回应并打印出⼊⼈数,所以界⾯我设计成这样:然后可以开始我们的点击事件启动服务啦⾸先我们创建负责监听的套接字,⽤到了 .Socket 下的寻址⽅案AddressFamily ,然后后⾯跟套接字类型,最后是⽀持的协议。
其中 WatchConnecting ⽅法是负责监听新客户端请求的其中接收数据 RecMsg⽅法如下:⼼得体会:其实整个流程并不复杂,但我遇到⼀个问题是,客户端每200毫秒发⼀次连接过来后,服务端会报⼀个远程主机已经强制关闭连接,开始我以为是我这边服务器线程间的问题或者是阻塞神马的,后来和客户端联调才发现问题,原来是服务器回应客户端⼼跳包的长度有问题,服务端定义的是1024字节,但是客户端只接受32字节的⼼跳包回应才会正确解析~所以,对接协议要沟通清楚,沟通清楚,沟通清楚,重要的事情说说三遍还有⼏个点值得注意1,有时候会遇到窗体间的控件访问异常,需要这样处理2多线程调试⽐较⿇烦,可以采⽤打印⽇志的⽅式,例如:具体实现可以参考我的另⼀篇博客:调⽤⽅法如下,注意,此处的package 的结构应该和协议中客户端发送的数据结构⼀致才能转换如协议中是这样的定义的话:Demo 下载 TCP 多线程服务器及客户端Demo密码:3hzsgit ⼀下:收发实体对象2017.3.11 补充如果服务器和客户端公⽤⼀个实体类,那还好说,如果服务器和客户端分别使⽤结构相同但不是同⼀个项⽬下的实体类,该如何⽤正确的姿势收发呢?⾸先简单看看效果如下:具体实现:因为前⾯提到不在同⼀项⽬下,如果直接序列化和反序列化,就会反序列化失败,因为不能对不是同⼀命名空间下的类进⾏此类操作,那么解决办法可以新建⼀个类库Studnet ,然后重新⽣成dll ,在服务器和客户端分别引⽤此dll ,就可以对此dll 进⾏序列化和反序列化操作了。
C#多线程编程中的锁系统(四):⾃旋锁⽬录⼀:基础⼆:⾃旋锁⽰例三:SpinLock四:继续SpinLock五:总结⼀:基础内核锁:基于内核对象构造的锁机制,就是通常说的内核构造模式。
优点:cpu利⽤最⼤化。
它发现资源被锁住,请求就排队等候。
线程切换到别处⼲活,直到接受到可⽤信号,线程再切回来继续处理请求。
缺点:托管代码->⽤户模式代码->内核代码损耗、线程上下⽂切换损耗。
在锁的时间⽐较短时,系统频繁忙于休眠、切换,是个很⼤的性能损耗。
⾃旋锁:原⼦操作+⾃循环。
通常说的⽤户构造模式。
线程不休眠,⼀直循环尝试对资源访问,直到可⽤。
优点:完美解决内核锁的缺点。
缺点:长时间⼀直循环会导致cpu的⽩⽩浪费,⾼并发竞争下、CPU的消耗特别严重。
混合锁:内核锁+⾃旋锁。
混合锁是先⾃旋锁⼀段时间或⾃旋多少次,再转成内核锁。
优点:内核锁和⾃旋锁的折中⽅案,利⽤前⼆者优点,避免出现极端情况(⾃旋时间过长,内核锁时间过短)。
缺点:⾃旋多少时间、⾃旋多少次,这些策略很难把控。
ps:操作系统或net框架,这块算法策略做的已经⾮常优了,有些API函数也提供了时间及次数可配置项,让开发者根据需求⾃⾏判断。
⼆:⾃旋锁⽰例来看下我们⾃⼰简单实现的⾃旋锁:复制代码代码如下:int signal = 0;var li = new List<int>();Parallel.For(0, 1000 * 10000, r =>{while (Interlocked.Exchange(ref signal, 1) != 0)//加⾃旋锁{//⿊魔法}li.Add(r);Interlocked.Exchange(ref signal, 0); //释放锁});Console.WriteLine(li.Count);//输出:10000000上⾯就是⾃旋锁:Interlocked.Exchange+while1:定义signal 0可⽤,1不可⽤。
c#多线程编程实例实战单个写⼊程序/多个阅读程序在.Net类库中其实已经提供了实现,即System.Threading.ReaderWriterLock类。
本⽂通过对常见的单个写⼊/多个阅读程序的分析来探索c#的多线程编程。
问题的提出 所谓单个写⼊程序/多个阅读程序的线程同步问题,是指任意数量的线程访问共享资源时,写⼊程序(线程)需要修改共享资源,⽽阅读程序(线程)需要读取数据。
在这个同步问题中,很容易得到下⾯⼆个要求: 1)当⼀个线程正在写⼊数据时,其他线程不能写,也不能读。
2)当⼀个线程正在读⼊数据时,其他线程不能写,但能够读。
在数据库应⽤程序环境中经常遇到这样的问题。
⽐如说,有n个最终⽤户,他们都要同时访问同⼀个数据库。
其中有m个⽤户要将数据存⼊数据库,n-m个⽤户要读取数据库中的记录。
很显然,在这个环境中,我们不能让两个或两个以上的⽤户同时更新同⼀条记录,如果两个或两个以上的⽤户都试图同时修改同⼀记录,那么该记录中的信息就会被破坏。
我们也不让⼀个⽤户更新数据库记录的同时,让另⼀⽤户读取记录的内容。
因为读取的记录很有可能同时包含了更新和没有更新的信息,也就是说这条记录是⽆效的记录。
实现分析 规定任⼀线程要对资源进⾏写或读操作前必须申请锁。
根据操作的不同,分为阅读锁和写⼊锁,操作完成之后应释放相应的锁。
将单个写⼊程序/多个阅读程序的要求改变⼀下,可以得到如下的形式: ⼀个线程申请阅读锁的成功条件是:当前没有活动的写⼊线程。
⼀个线程申请写⼊锁的成功条件是:当前没有任何活动(对锁⽽⾔)的线程。
因此,为了标志是否有活动的线程,以及是写⼊还是阅读线程,引⼊⼀个变量m_nActive,如果m_nActive > 0,则表⽰当前活动阅读线程的数⽬,如果m_nActive=0,则表⽰没有任何活动线程,m_nActive <0,表⽰当前有写⼊线程在活动,注意m_nActive<0,时只能取-1的值,因为只允许有⼀个写⼊线程活动。
C语⾔多线程操作多线程是多任务处理的⼀种特殊形式,多任务处理允许让电脑同时运⾏两个或两个以上的程序。
⼀般情况下,两种类型的多任务处理:基于进程和基于线程。
基于进程的多任务处理是程序的并发执⾏。
基于线程的多任务处理是同⼀程序的⽚段的并发执⾏。
多线程程序包含可以同时运⾏的两个或多个部分。
这样的程序中的每个部分称为⼀个线程,每个线程定义了⼀个单独的执⾏路径。
本教程假设您使⽤的是 Linux 操作系统,我们要使⽤ POSIX 编写多线程 C++ 程序。
POSIX Threads 或 Pthreads 提供的 API 可在多种类 Unix POSIX 系统上可⽤,⽐如 FreeBSD、NetBSD、GNU/Linux、Mac OS X 和 Solaris。
下⾯的程序,我们可以⽤它来创建⼀个POSIX 线程:#include <pthread.h>pthread_create (thread, attr, start_routine, arg)在这⾥,pthread_create 创建⼀个新的线程,并让它可执⾏。
下⾯是关于参数的说明:参数描述thread指向线程标识符指针。
attr⼀个不透明的属性对象,可以被⽤来设置线程属性。
您可以指定线程属性对象,也可以使⽤默认值 NULL。
start_routine线程运⾏函数起始地址,⼀旦线程被创建就会执⾏。
arg运⾏函数的参数。
它必须通过把引⽤作为指针强制转换为 void 类型进⾏传递。
如果没有传递参数,则使⽤ NULL。
创建线程成功时,函数返回 0,若返回值不为 0 则说明创建线程失败。
使⽤下⾯的程序,我们可以⽤它来终⽌⼀个 POSIX 线程:#include <pthread.h>pthread_exit (status)在这⾥,pthread_exit ⽤于显式地退出⼀个线程。
通常情况下,pthread_exit() 函数是在线程完成⼯作后⽆需继续存在时被调⽤。
用MFC实现多线程MFC(Microsoft Foundation Class)是微软公司提供的C++ 类库,用于开发 Windows 平台上的桌面应用程序。
MFC 提供了许多实用工具,用于简化 Windows 编程任务,包括多线程编程。
在本文中,我们将介绍如何使用 MFC 实现多线程。
多线程编程是指在一个程序中同时执行多个线程,每个线程都有自己的执行流程。
多线程编程可以提高程序的性能和响应速度,特别是在处理大量计算或耗时的任务时。
要在 MFC 中实现多线程,我们可以使用 CWinThread 类来创建和管理线程。
下面是一个简单的示例,演示了如何使用 MFC 创建一个多线程应用程序。
首先,我们需要在MFC应用程序的主类中添加一个成员函数,该函数将被作为线程函数调用。
在这个示例中,我们将创建一个计算从1到100的和的线程。
```cppUINT CalculationThread(LPVOID pParam)int sum = 0;for (int i = 1; i <= 100; i++)sum += i;}CString strResult;strResult.Format(_T("Sum is %d"), sum);AfxMessageBox(strResult);return 0;}```接下来,在应用程序的`InitInstance`函数中创建线程对象并启动线程。
```cppBOOL CMyApp::InitInstance//...//创建线程对象CWinThread* pThread = AfxBeginThread(CalculationThread, NULL);//...return TRUE;```通过调用`AfxBeginThread`函数,我们将线程函数`CalculationThread`和参数指针`NULL`传递给 MFC,以创建一个新的线程。
C多线程编程实例实战Prepared on 21 November 2021
C#多线程编程实例实战
问题的提出
所谓单个写入程序/多个阅读程序的线程同步问题,是指任意数量的线程访问共享资源时,写入程序(线程)需要修改共享资源,而阅读程序(线程)需要读取数据。
在这个同步问题中,很容易得到下面二个要求: 1)当一个线程正在写入数据时,其他线程不能写,也不能读。
2)当一个线程正在读入数据时,其他线程不能写,但能够读。
在数据库应用程序环境中经常遇到这样的问题。
比如说,有n个最终用户,他们都要同时访问同一个数据库。
其中有m个用户要将数据存入数据库,n-m个用户要读取数据库中的记录。
很显然,在这个环境中,我们不能让两个或两个以上的用户同时更新同一条记录,如果两个或两个以上的用户都试图同时修改同一记录,那么该记录中的信息就会被破坏。
我们也不让一个用户更新数据库记录的同时,让另一用户读取记录的内容。
因为读取的记录很有可能同时包含了更新和没有更新的信息,也就是说这条记录是无效的记录。
实现分析
规定任一线程要对资源进行写或读操作前必须申请锁。
根据操作的不同,分为阅读锁和写入锁,操作完成之后应释放相应的锁。
将单个写入程序/多个阅读程序的要求改变一下,可以得到如下的形式:
一个线程申请阅读锁的成功条件是:当前没有活动的写入线程。
一个线程申请写入锁的成功条件是:当前没有任何活动(对锁而言)的线程。
因此,为了标志是否有活动的线程,以及是写入还是阅读线程,引入一个变量m_nActive,如果m_nActive > 0,则表示当前活动阅读线程的数目,如果m_nActive=0,则表示没有任何活动线程,m_nActive <0,表示当前有写入线程在活动,注意m_nActive<0,时只能取-1的值,因为只允许有一个写入线程活动。
为了判断当前活动线程拥有的锁的类型,我们采用了线程局部存储技术(请参阅其它参考书籍),将线程与特殊标志位关联起来。
申请阅读锁的函数原型为:public void AcquireReaderLock( int millisecondsTimeout ),其中的参数为线程等待调度的时间。
函数定义如下:public void AcquireReaderLock( int millisecondsTimeout )
{
et FrameSDK中的一个例子,只是稍做修改。
测试程序如下,
using System;
using ;
using MyThreading;
class Resource {
myReaderWriterLock rwl = new myReaderWriterLock();
public void Read(Int32 threadNum) {
;
try {
("Start Resource reading (Thread={0})", threadNum);
(250);
("Stop Resource reading (Thread={0})", threadNum);
}
finally {
();
}
}
public void Write(Int32 threadNum) {
;
try {
("Start Resource writing (Thread={0})", threadNum);
(750);
("Stop Resource writing (Thread={0})", threadNum);
}
finally {
();
}
}
}
class App {
static Int32 numAsyncOps = 20;
static AutoResetEvent asyncOpsAreDone = new AutoResetEvent(false); static Resource res = new Resource();
public static void Main() {
for (Int32 threadNum = 0; threadNum < 20; threadNum++) {
(new WaitCallback(UpdateResource), threadNum);
}
();
("All operations have completed.");
();
}
// The callback method's signature MUST match that of a
// delegate (it takes an Object parameter and returns void)
static void UpdateResource(Object state) {
Int32 threadNum = (Int32) state;
if ((threadNum % 2) != 0) (threadNum);
else (threadNum);
if (ref numAsyncOps) == 0)
();
}
}
从测试结果中可以看出,可以满足单个写入程序\多个阅读程序的实现要求。