C#多线程学习(三)生产者和消费者

前面说过,每个线程都有自己的资源,但是代码区是共享的,即每个线程都可以执行相同的函数。这可能带来的问题就是几个线程同时执行一个函数,导致数据的混乱,产生不可预料的结果,因此我们必须避免这种情况的发生。

C#提供了一个关键字lock,它可以把一段代码定义为互斥段(critical section),互斥段在一个时刻内只允许一个线程进入执行,而其他线程必须等待。在C#中,关键字lock定义如下:

lock(expression) statement_block

expression代表你希望跟踪的对象,通常是对象引用。

如果你想保护一个类的实例,一般地,你可以使用this;

如果你想保护一个静态变量(如互斥代码段在一个静态方法内部),一般使用类名就可以了。

而statement_block就是互斥段的代码,这段代码在一个时刻内只可能被一个线程执行。

下面是一个使用lock关键字的典型例子,在注释里说明了lock关键字的用法和用途。

示例如下:

using System;
using System.Threading;
namespace ThreadSimple
{
internal class Account
{
int balance;
Random r = new Random();

internal Account(int initial)
{
balance = initial;
}
internal int Withdraw(int amount)
{
if (balance < 0)
{
//如果balance小于0则抛出异常
throw new Exception("Negative Balance");
}
//下面的代码保证在当前线程修改balance的值完成之前
//不会有其他线程也执行这段代码来修改balance的值
//因此,balance的值是不可能小于0 的
lock (this)
{
Console.WriteLine("Current Thread:"+Thread.CurrentThread.Name);
//如果没有lock关键字的保护,那么可能在执行完if的条件判断之后
//另外一个线程却执行了balance=balance-amount修改了balance的值
//而这个修改对这个线程是不可见的,所以可能导致这时if的条件已经不成立了
//但是,这个线程却继续执行balance=balance-amount,所以导致balance可能小于0
if (balance >= amount)
{
Thread.Sleep(5);
balance = balance - amount;
return amount;
}
else
{
return 0; // transaction rejected
}
}
}
internal void DoTransactions()
{
for (int i = 0; i < 100; i++)
Withdraw(r.Next(-50, 100));
}
}
internal class Test
{
static internal Thread[] threads = new Thread[10];
public static void Main()
{
Account acc = new Account (0);
for (int i = 0; i < 10; i++)
{
Thread t = new Thread(new ThreadStart(acc.DoTransactions));
threads[i] = t;
}
for (int i = 0; i < 10; i++)
threads[i].Name=i.ToString();
for (int i = 0; i < 10; i++)
threads[i].Start();
Console.ReadLine();
}
}
}

时间: 2024-10-02 11:59:18

C#多线程学习(三)生产者和消费者的相关文章

linux多线程学习(三)——线程属性设置。

在上一篇文章中,介绍了线程的创建和退出,以及相关函数的使用.其中pthread_create函数的第二个参数,是关于线程属性的设置,这也是今天所有讲述的.这些属性主要包括邦定属性.分离属性.堆栈地址.堆栈大小.优先级.其中系统默认的是非邦定.非分离.缺省1M的堆栈.与父进程同样级别的优先级.在pthread_create中,把第二个参数设置为NULL的话,将采用默认的属性配置. (1)绑定属性. 在LINUX中,采用的是"一对一"的线程机制.也就是一个用户线程对应一个内核线程.邦定属性

艾伟:C#多线程学习(四) 多线程的自动管理(线程池)

本系列文章导航 C#多线程学习(一) 多线程的相关概念 C#多线程学习(二) 如何操纵一个线程 C#多线程学习(三) 生产者和消费者 C#多线程学习(四) 多线程的自动管理(线程池) C#多线程学习(五) 多线程的自动管理(定时器) C#多线程学习(六) 互斥对象 在多线程的程序中,经常会出现两种情况: 一种情况: 应用程序中,线程把大部分的时间花费在等待状态,等待某个事件发生,然后才能给予响应 这一般使用ThreadPool(线程池)来解决: 另一种情况:线程平时都处于休眠状态,只是周期性地被

艾伟:C#多线程学习(五) 多线程的自动管理(定时器)

本系列文章导航 C#多线程学习(一) 多线程的相关概念 C#多线程学习(二) 如何操纵一个线程 C#多线程学习(三) 生产者和消费者 C#多线程学习(四) 多线程的自动管理(线程池) C#多线程学习(五) 多线程的自动管理(定时器) C#多线程学习(六) 互斥对象 Timer类:设置一个定时器,定时执行用户指定的函数. 定时器启动后,系统将自动建立一个新的线程,执行用户指定的函数. 初始化一个Timer对象: Timer timer = new Timer(timerDelegate, s,10

JAVA之旅(十五)——多线程的生产者和消费者,停止线程,守护线程,线程的优先级,setPriority设置优先级,yield临时停止

JAVA之旅(十五)--多线程的生产者和消费者,停止线程,守护线程,线程的优先级,setPriority设置优先级,yield临时停止 我们接着多线程讲 一.生产者和消费者 什么是生产者和消费者?我们解释过来应该是生产一个,消费一个,的意思,具体我们通过例子来说 package com.lgl.hellojava; //公共的 类 类名 public class HelloJJAVA { public static void main(String[] args) { /** * 生产者和消费者

linux多线程学习(七)——实现“生产者和消费者”

在上一篇文章中,利用信号量实现了线程间的互斥,这一篇将要利用信号量的互斥同步机制来实现一个经典实例,就是"生产者和消费者". 1.简单描述生产者和消费者的问题. 有一个缓冲区和两个线程:生产者和消费者.生产者把产品放入缓冲区,而消费者从缓冲区中拿走.当缓冲区满时,生产者必须等待:另外,当缓冲区空时,消费者必须等待,并且缓冲区不能同时进行生产者和消费者的操作. [cpp:nogutter] view plaincopy #include <stdio.h>     #incl

并发无锁队列学习之二【单生产者单消费者】

1.前言 最近工作比较忙,加班较多,每天晚上回到家10点多了.我不知道自己还能坚持多久,既然选择了就要做到最好.写博客的少了.总觉得少了点什么,需要继续学习.今天继续上个开篇写,介绍单生产者单消费者模型的队列.根据写入队列的内容是定长还是变长,分为单生产者单消费者定长队列和单生产者单消费者变长队列两种.单生产者单消费者模型的队列操作过程是不需要进行加锁的.生产者通过写索引控制入队操作,消费者通过读索引控制出队列操作.二者相互之间对索引是独享,不存在竞争关系.如下图所示: 2.单生产者单消费者定长

java 多线程生产者和消费者模式,怎么实现边生产边消费?

问题描述 java 多线程生产者和消费者模式,怎么实现边生产边消费? 如何使用java语言开发处理一批数据,使处理时间变快,而又不遗漏数据呢?? 解决方案 看瓶颈在哪里,如果是cpu.io的开销,性能不可能无限提高.如果存在网络延迟等,可以用多线程隐藏延迟,达到提高性能的目的. 解决方案二: 你说的什么叫边生产边消费呢?生产者消费者设计实现设计中生产者把数据放入队列,消费者从队列中获取数据处理,消除了生产者和消费者之间的代码依赖.该模式将生产数据的过程与使用数据的过程解耦,简化了由于这两个过程不

生产者消费者问题-秒杀多线程中生产者与消费者问题并行问题

问题描述 秒杀多线程中生产者与消费者问题并行问题 在模仿博文秒杀多线程问题生产者与消费者问题写多线程程序,实现了多线程的编程,但是有没有实现多线程的并行处理呢?体现在哪里?理论上是不是仍是串行实现?求大神指教 解决方案 你说的是哪一篇博客中的代码,贴一下链接 解决方案二: [多线程](九)生产者消费者问题

Java经典多线程问题--生产者与消费者

今天研究了一下Java多线程,顺便写了一下多线程中的经典问题-–生产者消费者经典问题,推荐一个线程链接Java基础知识回顾–线程 这个里面其实写了生产者与消费者问题,估计在后面大家看起来比较费劲,所以我提取出来再讲解一遍. package yanning; public class ProducerConsumer { public static void main(String[] args) { Tong tong = new Tong(); Producer p = new Produce