C# 多线程操作

本文详细介绍了C#中的多线程操作,包括线程的概念、创建与使用,以及线程安全问题。通过示例代码展示了如何创建线程、共享数据、处理异常,并讨论了何时使用和不使用多线程的场景。强调了线程安全的重要性以及如何通过锁机制保证数据一致性。
摘要由CSDN通过智能技术生成

概述与概念

C#支持通过多线程并行地执行代码,一个线程有它独立的执行路径,能够与其它的线程同时地运行。一个C#程序开始于一个单线程,这个单线程是被CLR和操作系统(也称为“主线程”)自动创建的,并具有多线程创建额外的线程。这里的一个简单的例子及其输出:

除非被指定,否则所有的例子都假定以下命名空间被引用了:
using System;
using System.Threading;

class ThreadTest {
  
static void Main() {
  
       Thread t = new Thread (WriteY);
       t.Start();                             // 在新的线程中运行WriteY
       while (true) Console.Write ("x");      // 不停地写'x'
}
 
static void WriteY() {
  
       while (true) Console.Write ("y");      // 不停地写'y'
}
}

xxxxxxxxxxxxxxxxyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxyyyyyyyyyyyyy
yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
yyyyyyyyyyyyyxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
...

主线程创建了一个新线程“t”,它运行了一个重复打印字母"y"的方法,同时主线程重复但因字母“x”。CLR分配每个线程到它自己的内存堆栈上,来保证局部变量的分离运行。在接下来的方法中我们定义了一个局部变量,然后在主线程和新创建的线程上同时地调用这个方法。

static void Main() {
  
new Thread (Go).Start();      // 调用Go()方法在一个新线程中
Go();                         // 在主线程中调用Go()
}
 
static void Go() {
  
// 声明和使用一个局部变量'cycles'
for (int cycles = 0; cycles < 5; cycles++) Console.Write ('?');
}

??????????

变量cycles的副本分别在各自的内存堆栈中创建,输出也一样,可预见,会有10个问号输出。当线程们引用了一些公用的目标实例的时候,他们会共享数据。下面是实例:

class ThreadTest {
  
bool done;
 
static void Main() {
  
ThreadTest tt = new ThreadTest();   // 创建一个实例
   new Thread (tt.Go).Start();
      tt.Go();
}
 
// 注意Go现在是一个实例方法
void Go() {
  
   if (!done) { done = true; Console.WriteLine ("Done"); }
}
}

因为在相同的ThreadTest实例中,两个线程都调用了Go(),它们共享了done字段,这个结果输出的是一个"Done",而不是两个。

Done

静态字段提供了另一种在线程间共享数据的方式,下面是一个以done为静态字段的例子:

class ThreadTest {
  
static bool done;    // 静态方法被所有 线程一块使用
 
static void Main() {
  
   new Thread (Go).Start();
      Go();
}
 
static void Go() {
  
   if (!done) { done = true; Console.WriteLine ("Done"); }
}
}

上述两个例子足以说明, 另一个关键概念, 那就是线程安全(或反之,它的不足之处! ) 输出实际上是不确定的:它可能(虽然不大可能) , "Done" ,可以被打印两次。然而,如果我们在Go方法里调换指令的顺序, "Done"被打印两次的机会会大幅地上升:

static void Go() {
  
if (!done) { Console.WriteLine ("Done"); done = true; }
}

Done
Done

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值