C多线程编程实例实战

合集下载

c++多线程实现方法

c++多线程实现方法

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#多线程编程实战(一):线程基础

C#多线程编程实战(一):线程基础

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获取线程的运⾏状态。

多线程程序实验报告(3篇)

多线程程序实验报告(3篇)

第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)】

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 多线程编程例子

vc++2019 多线程编程例子

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 Studio C#的应用实例教程

多线程在Visual Studio 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#实现多线程的同步方法详解

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语言程序设计案例
以下是一个简单的 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下的CC++多进程多线程编程实例详解

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);}感谢阅读,希望能帮助到⼤家,谢谢⼤家对本站的⽀持!。

用MFC编写多线程程序实例

用MFC编写多线程程序实例
在很多情况下,需要采用多线程技术进行程序设计。例如,常用的字处理软件Word,当输入文字的时候,Word同时进行拼写和语法的检验,也就是将文档中的词语与词库中的词语进行比较,并对文档中的语句进行语法分析。这些操作都比较耗费时间,但是我们在使用Word的时候并没有感觉到输入过程有明显的滞后现象。这里Word就采用了多线程技术,其中一个线程接收输入,另一个线程进行拼写和语法的检验。
class CWzdData public CObject
{
public
DECLARE_SERIAL( CWzdData )
CWzdData();
BOOL GetData(int pInt,float pFloat,DWORD pWord);
{ }
CreateMutex()函数的功能并不仅仅只是追踪应用程序的实例。在该实例中只是简单使用其中的部分功能。
具体的程序实现代码如下:
#ifndef WZDDATA _ H
#define WZDDATA _ H
#include
3、在时间要求严格的应用程序(例如实时应用程序)中,不希望因为工作者线程启动而等待,这时可将工作者线程中的控制逻辑内置到用户界面线程中并提前创建线程。当需要处理事务时,向用户界面线程发送消息,此时用户界面线程已经运行并且在等待指令。
程序清单:
#if !defined(AFX_WZDTHREAD_H__411AE4C2_E515_11D1_9B80_00AA003D8695__INCLUDED_)
CMutex mutex[2];
mutex[0] = &mutex1;
mutex[1] = &mutex2;
CMultiLock mlock( mutex,2 ); where 2 is the number of mutexes

c语言多线程编程实例

c语言多线程编程实例

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多线程服务器示例

C#TCP多线程服务器示例

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#多线程编程中的锁系统(四):自旋锁

C#多线程编程中的锁系统(四):自旋锁

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#多线程编程实例实战

c#多线程编程实例实战

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语言多线程操作

C语言多线程操作

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() 函数是在线程完成⼯作后⽆需继续存在时被调⽤。

基于VC++的多线程编程实现

基于VC++的多线程编程实现
VOI n e Crt a S ci nf D E t r ii l e t c o
L CR IALs C IN l ri l ei Eettiue, /} 区指 针 P ITC _E TO Cie S tn vnAtb t / I界 p ta e o r s 缶 ); V I evCiclet n OD L ae ri Sc o ( ta i L CI TI P R CAL S C I p ri Sc oE e tt bt ,/ 界 区 指 E TON lCie etn vnAt ue / 临 ta l i r i s

L c T N m ;/ P Rl a e) / 对象名字 p ③ 创建事件 函数
H ND EC etE et A L ra vn( e LS P ECURIY A F IU E E etti t , 指 向一个 结 构 , T T R B T S l vnAtb e / p ru s / 说 明句柄是 否能被某个子线程继承 , 如果为 N L , U L 则不能继承 B OLb naR st/ 重置类型 O Ma ulee,/ B O lia tt, / O Lbnt Sae / 明确事件对象的初始对象 i l L C S R lN me / 对 象 名 字 PTT a ,/ p ) ;
V C+ +中提供 的 MF C类库 。 实现 一 个 多线 程 的 编 程 实例 。
【 关键词 】 线程
句柄
临界 区 线程控制
中图分 类号 :P 1 文献标识码 : 文章编号 :0 9— 07(00)3—0 6 0 T3 1 A 10 4 6 2 1 0 0 1— 2
现代操作系统具有并发性 、 共享性 、 虚拟性和异步性四个特征 , 而具 有这 四个特征的操作系统 中, 线程作为最核心的概念在操 作系统基础概 念中占有很重要的地位 , 随操作系统 的发展 , 且 多进 程和多线程 的编程 已成 为 目前软件设计的重要方法 , V 在 C++中, 提供了用 多线程编程 的 丰富手段 。

用MFC实现多线程

用MFC实现多线程

用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,以创建一个新的线程。

vc6.0开发多线程程序基础教程

vc6.0开发多线程程序基础教程

1、HANDLE CreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes,
DWORD dwStackSize,
LPTHREAD_START_ROUTINE lpStartAddress,
该函数用于结束线程的挂起状态,执行线程。 4、VOID ExitThread(DWORD dwExitCode);
该函数用于线程终结自身的执行,主要在线程的执行函数中被调用。其中参数dwExitCode用来设置线程的退出码。 5、BOOL TerminateThread(HANDLE hThread,DWORD dwExitCode);
在MultiThread2Dlg.h文件中添加线程函数声明: void ThreadFunc(int integer);
注意,线程函数的声明应在类CMultiThread2Dlg的外部。
在类CMultiThread2Dlg内部添加protected型变量: HANDLE hThread;
::SetDlgItemText(AfxGetMainWnd()->m_hWnd,IDC_TIME,strTime);
Sleep(1000);
}
}
该线程函数没有参数,也不返回函数值。只要m_bRun为TRUE,线程一直运行。
双击IDC_STARTቤተ መጻሕፍቲ ባይዱ钮,完成该按钮的消息函数: void CMultiThread1Dlg::OnStart()
{
Beep(200,50);
Sleep(1000);
}
}
双击IDC_START按钮,完成该按钮的消息函数: void CMultiThread2Dlg::OnStart()

C++一个网络编程实例

C++一个网络编程实例

C++⼀个⽹络编程实例学习C++已经有⼀段时间了,⼀直都是学习基础的东西,每次写的代码都⽐较少,没有明确的学习⽬标,基础还是基础,漫⽆边际的,基本上都是做⼀道或者⼏道算法题,连⼀个⼩⼩的实战都没有,也不知道⾃⼰学得怎么样了,现在终于有⼀个⼩⼩的实战了《C++ ⼀个⽹络编程实例》。

由于⾃⼰⼀直在做C#,只能业余时间学习C++,都说C++ 是那么的难,暂时还没有感觉到有多难,毕竟写代码也有两年多了。

我要学习多久才能进⼀家做C++研发的公司呢?相信在不远处有⼀家C++研发公司在等着我。

这只是⼀个⼩⼩的实例,包括Socket编程、多线程、⽂件操作。

简单介绍:他实现了点对点聊天,⼀个服务器,⼀个客户端,主线程⽤来发送数据,启动⼀个⼦线程⽤来接收数据,服务器记录聊天内容。

他只是⽤上了上⾯所说的三个技术,如果你对上⾯三个技术不是很熟,或许对你有点帮助,如果你很熟,既然来了希望你能指导⼀下我,如果你是⾼⼿希望你能指导⼀下我的编码问题。

我太渴望写出⾼效简洁的代码。

废话就少说了,程序⾥处处都是注释,你可以选择看看我的代码,或是选择直接运⾏看看,《》。

服务器代码:// Server.cpp : 定义控制台应⽤程序的⼊⼝点。

#include "stdafx.h"#include <windows.h>#include <process.h>#include <iostream>#include "FileLog.h"#include "time.h"using namespace std;#pragma comment(lib,"ws2_32.lib")//多线程调⽤的⽅法只有⼀个指针型的参数,有时候需要多个参数,所以定义⼀个结构,参数作为结构的字段typedef struct _receiveStruct{SOCKET *Socket;FileLog *fileLog;_receiveStruct(SOCKET *_socket,FileLog *_fileLog):Socket(_socket),fileLog(_fileLog){}} ReceiveStruct;//获取今天⽇期的字符串string GetDate(const char *format){time_t tm;struct tm *now;char timebuf[20];time(&tm);now=localtime(&tm);strftime(timebuf,sizeof(timebuf)/sizeof(char),format,now);return string(timebuf);}//接收数据线程void receive(PVOID param){ReceiveStruct* receiveStruct=(ReceiveStruct*)param;char buf[2048];int bytes;while(1){//接收数据if((bytes=recv(*receiveStruct->Socket,buf,sizeof(buf),0))==SOCKET_ERROR){cout<<"接收数据失败!\n";_endthread();//终⽌当前线程}buf[bytes]='\0';cout<<"客户端说:"<<buf<<endl;receiveStruct->fileLog->Write("客户端 ").WriteLine(GetDate("%Y-%m-%d %H:%M:%S").c_str()).WriteLine(buf);//记录聊天内容}}//获取本机IPin_addr getHostName(void){char host_name[255];if (gethostname(host_name, sizeof(host_name)) == SOCKET_ERROR) {cout<<"Error %d when getting local host name."<<WSAGetLastError();Sleep(3000);exit(-1);}//从主机名数据库中得到对应的“IP”struct hostent *phe = gethostbyname(host_name);if (phe == 0) {cout<<"Yow! Bad host lookup.";Sleep(3000);exit(-1);}struct in_addr addr;memcpy(&addr, phe->h_addr_list[0], sizeof(struct in_addr));return addr;}//启动服务器SOCKET StartServer(void){//创建套接字SOCKET serverSocket;if((serverSocket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP))==INVALID_SOCKET){cout<<"创建套接字失败!";Sleep(3000);exit(-1);}short port=1986;struct sockaddr_in serverAddress;//初始化指定的内存区域memset(&serverAddress,0,sizeof(sockaddr_in));serverAddress.sin_family=AF_INET;serverAddress.sin_addr.S_un.S_addr = htonl(INADDR_ANY);serverAddress.sin_port = htons(port);//绑定if(bind(serverSocket,(sockaddr*)&serverAddress,sizeof(serverAddress))==SOCKET_ERROR){cout<<"套接字绑定到端⼝失败!端⼝:"<<port;Sleep(3000);exit(-1);}//进⼊侦听状态if(listen(serverSocket,SOMAXCONN)==SOCKET_ERROR){cout<<"侦听失败!";Sleep(3000);exit(-1);}//获取服务器IPstruct in_addr addr = getHostName();cout<<"Server "<<inet_ntoa(addr)<<" : "<<port<<" is listening......"<<endl;return serverSocket;}//接收客户端连接SOCKET ReceiveConnect(SOCKET &serverSocket){SOCKET clientSocket;//⽤来和客户端通信的套接字struct sockaddr_in clientAddress;//⽤来和客户端通信的套接字地址memset(&clientAddress,0,sizeof(clientAddress));//初始化存放客户端信息的内存int addrlen = sizeof(clientAddress);//接受连接if((clientSocket=accept(serverSocket,(sockaddr*)&clientAddress,&addrlen))==INVALID_SOCKET){ cout<<"接受客户端连接失败!";Sleep(3000);exit(-1);}cout<<"Accept connection from "<<inet_ntoa(clientAddress.sin_addr)<<endl;return clientSocket;}//发送数据void SendMsg(SOCKET &clientSocket,FileLog &fileLog){char buf[2048];if(send(clientSocket,buf,strlen(buf),0)==SOCKET_ERROR){cout<<"发送数据失败!"<<endl;Sleep(3000);exit(-1);}fileLog.Write("服务器 ").WriteLine(GetDate("%Y-%m-%d %H:%M:%S").c_str()).WriteLine(buf);//记录聊天内容 }}int main(int argc, char* argv[]){WSADATA wsa;//WSADATA结构被⽤来保存函数WSAStartup返回的Windows Sockets初始化信息//MAKEWORD(a,b)是将两个byte型合并成⼀个word型,⼀个在⾼8位(b),⼀个在低8位(a)if(WSAStartup(MAKEWORD(2,2),&wsa)!=0){cout<<"套接字初始化失败!";Sleep(3000);exit(-1);}SOCKET serverSocket=StartServer();//启动服务器SOCKET clientSocket=ReceiveConnect(serverSocket);//接收客服端的链接FileLog fileLog;fileLog.Open(GetDate("%Y%m%d").append(".log").c_str());//打开记录聊天内容⽂件ReceiveStruct receiveStruct(&clientSocket,&fileLog);_beginthread(receive,0,&receiveStruct);//启动⼀个接收数据的线程SendMsg(clientSocket,fileLog);//发送数据fileLog.Close();//关闭⽂件closesocket(clientSocket);//关闭客户端套接字(马上发送FIN信号,所有没有接收到或是发送完成的数据都会丢失) closesocket(serverSocket);//关闭服务器套接字//清理套接字占⽤的资源WSACleanup();return 0;} 客户端代码:// Client.cpp#include "stdafx.h"#include <windows.h>#include <process.h>#include <iostream>using namespace std;#pragma comment(lib,"ws2_32.lib")//接收数据void Receive(PVOID param){char buf[2096];while(1){SOCKET* sock=(SOCKET*)param;int bytes;if((bytes=recv(*sock,buf,sizeof(buf),0))==SOCKET_ERROR){printf("接收数据失败!\n");exit(-1);}buf[bytes]='\0';cout<<"服务器说:"<<buf<<endl;}}//获取服务器IPunsigned long GetServerIP(void){//把字符串的IP地址转化为u_longchar ipStr[20];//⽤第⼆个参数填充第⼀个参数所指的内存,填充的长度为第三个参数的⼤⼩memset(ipStr,0,sizeof(ipStr));cout<<"请输⼊你要链接的服务器IP:";cin>>ipStr;unsigned long ip;if((ip=inet_addr(ipStr))==INADDR_NONE){cout<<"不合法的IP地址:";}return ip;}//链接服务器void Connect(SOCKET &sock){unsigned long ip=GetServerIP();//把端⼝号转化成整数short port=1986;cout<<"Connecting to "<<inet_ntoa(*(in_addr*)&ip)<<" : "<<port<<endl;struct sockaddr_in serverAddress;memset(&serverAddress,0,sizeof(sockaddr_in));serverAddress.sin_family=AF_INET;serverAddress.sin_addr.S_un.S_addr= ip;serverAddress.sin_port = htons(port);//建⽴和服务器的连接if(connect(sock,(sockaddr*)&serverAddress,sizeof(serverAddress))==SOCKET_ERROR){ cout<<"建⽴连接失败:"<<WSAGetLastError();Sleep(3000);exit(-1);}}//发送数据void SendMsg(SOCKET &sock){char buf[2048];while(1){//从控制台读取⼀⾏数据gets_s(buf);cout<<"我说:";//发送给服务器if(send(sock,buf,strlen(buf),0)==SOCKET_ERROR){cout<<"发送数据失败!";exit(-1);}}}int main(int argc, char* argv[]){WSADATA wsa;//初始化套接字DLLif(WSAStartup(MAKEWORD(2,2),&wsa)!=0){cout<<"套接字初始化失败!";Sleep(3000);exit(-1);}//创建套接字SOCKET sock;if((sock=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP))==INVALID_SOCKET){cout<<"创建套接字失败!";exit(-1);}Connect(sock);//链接服务器_beginthread(Receive,0,&sock);//启动接收数据线程SendMsg(sock);//发送数据//清理套接字占⽤的资源WSACleanup();return 0;} ⽂件操作代码(FileLog.h):#include "iostream"#include "string.h"#include <windows.h>using namespace std;class FileLog{private:CRITICAL_SECTION cs;HANDLE fileHandle;{EnterCriticalSection(&cs);// 进⼊临界区}void UnLock(){LeaveCriticalSection(&cs);//离开临界区}public:FileLog(){InitializeCriticalSection(&cs);//初始化临界区fileHandle=INVALID_HANDLE_VALUE;//先初始化为错误的句柄}~FileLog(){if(fileHandle!=INVALID_HANDLE_VALUE){//CloseHandle的功能是关闭⼀个打开的对象句柄,该对象句柄可以是线程句柄,也可以是进程、信号量等其他内核对象的句柄 CloseHandle(fileHandle);}DeleteCriticalSection(&cs);//删除临界区}BOOL Open(const char *fileName);//打开⽂件FileLog& Write(const char *content);//向⽂件中写⼊内容FileLog& WriteLine(const char *content);//向⽂件中写⼊内容BOOL Read(char *buf,int size);//读⽂件内容BOOL Close();//关闭⽂件}; ⽂件操作代码(FileLog.app):#include "stdafx.h"#include "FileLog.h"//打开⽂件BOOL FileLog::Open(const char *fileName){if(fileHandle==INVALID_HANDLE_VALUE){fileHandle=CreateFile(fileName,GENERIC_WRITE|GENERIC_READ,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);if(fileHandle!=INVALID_HANDLE_VALUE){SetFilePointer(fileHandle,0,NULL,FILE_END);return TRUE;}}return FALSE;}//写⽂件返回当前对象的引⽤,实现连接操作FileLog& FileLog::Write(const char *content){Lock();if(fileHandle!=INVALID_HANDLE_VALUE){DWORD dwSize=0;WriteFile(fileHandle,content,strlen(content),&dwSize,NULL);//写}//开始的时候少写了这句,由于加的锁没有释放,⼀个线程占⽤之后,导致其他线程只能⼀直等待,好久都没有找到原因。

Linux下C多线程编程实例

Linux下C多线程编程实例

Linux下C多线程编程实例Linux下C多线程编程2007-08-24 10:07:56Linux系统下的多线程遵循POSIX线程接口,称为pthread。

编写Linux下的多线程程序,需要使用头文件pthread.h,连接时需要使用库libpthread.a。

顺便说一下,Linux下pthread的实现是通过系统调用clone()来实现的。

clone()是Linux所特有的系统调用,它的使用方式类似fork,关于clone()的详细情况,有兴趣的读者可以去查看有关文档说明。

下面我们展示一个最简单的多线程程序example1.c。

我们编译此程序:运行example1,我们得到如下结果:再次运行,我们可能得到如下结果:前后两次结果不一样,这是两个线程争夺CPU资源的结果。

上面的示例中,我们使用到了两个函数,pthread_create和pthread_join,并声明了一个pthread_t型的变量。

pthread_t在头文件/usr/include/bits/pthreadtypes.h中定义:typedef unsigned long int pthread_t;它是一个线程的标识符。

函数pthread_create用来创建一个线程,它的原型为:第一个参数为指向线程标识符的指针,第二个参数用来设置线程属性,第三个参数是线程运行函数的起始地址,最后一个参数是运行函数的参数。

这里,我们的函数thread不需要参数,所以最后一个参数设为空指针。

第二个参数我们也设为空指针,这样将生成默认属性的线程。

对线程属性的设定和修改我们将在下一节阐述。

当创建线程成功时,函数返回0,若不为0则说明创建线程失败,常见的错误返回代码为EAGAIN和EINVAL。

前者表示系统限制创建新的线程,例如线程数目过多了;后者表示第二个参数代表的线程属性值非法。

创建线程成功后,新创建的线程则运行参数三和参数四确定的函数,原来的线程则继续运行下一行代码。

相关主题
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

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)
();
}
}
从测试结果中可以看出,可以满足单个写入程序\多个阅读程序的实现要求。

相关文档
最新文档