当前位置:文档之家› C#跨线程访问控件

C#跨线程访问控件

C#跨线程访问控件
C#跨线程访问控件

C#跨线程访问控件

在用CS结构开发系统时,我们常会使用到多线程来处理程序,其中一个就是使用跨线程访问控件或设置控件属性。如果这样,在调试时会提示出错,不能在其它线程中修改创建控件的线程的控件的值。这是因为.net 2.0以后加强了安全机制,不允许在winform中直接跨线程访问控件的属性。

我们先看一下传统的程序:

设计界面如下:在窗体中添加一个Label控件(用来显示时间)

图1

源程序:

using System;

using System.Windows.Forms;

using System.Threading;

namespace KingChat

{

public partial class SystemLogin : DevExpress.XtraEditors.XtraForm {

public SystemLogin()

{

InitializeComponent();

}

private void SystemLogin_Load(object sender, EventArgs e)

{

Thread newThread = new Thread(new ThreadStart(threadFuntion));

newThread.IsBackground = true;

newThread.Start();

}

private void threadFuntion()

{

while (true)

{

https://www.doczj.com/doc/f310384999.html,bel1.Text = DateTime.Now.ToString();

Thread.Sleep(1000);

}

}

}

}

当调试上面的程序是会提示出错:

图2

如果你是直接运行程序生成的可执行文件就得到得到如下界面:

图3

原因是:.NET 原则上禁止跨线程访问控件,因为这样可能造成错误的发生。

那么我们有什么方法解决C#跨线程访问控件问题:

1)禁止编译器对跨线程访问作检查,可以实现访问,但是出不出错不敢保证;

2)推荐的解决方法是采用代理,用代理方法来间接操作不是同一线程创建的控件。

解决方案一:

利用Control.CheckForIllegalCrossThreadCalls = false; 加入这句代码调试时也不会提示出错,可以正常执行下面的程序。这句代码就是说在这个类中我们不

检查跨线程的调用是否合法(如果没有加这句话运行也没有异常,那么说明系统以及默认的采用了不检查的方式)。然而,这种方法不可取。我们查看CheckForIllegalCrossThreadCalls 这个属性的定义,就会发现它是一个static的,也就是说无论我们在项目的什么地方修改了这个值,他就会在全局起作用。而且像这种跨线程访问是否存在异常,我们通常都会去检查。如果项目中其他人修改了这个属性,那么我们的方案就失败了,我们要采取另外的方案。

具体做法如下:

在窗体的Load方法中加入代码,其他不变

private void SystemLogin_Load(object sender, EventArgs e)

{

Control.CheckForIllegalCrossThreadCalls = false;

Thread newThread = new Thread(new ThreadStart(threadFuntion));

newThread.IsBackground = true;

newThread.Start();

}

解决方案二:

就是使用delegate和invoke来从其他线程中控制控件信息。

源代码如下:

using System;

using System.Windows.Forms;

using System.Threading;

namespace KingChat

{

public partial class SystemLogin : DevExpress.XtraEditors.XtraForm

{

private delegate void DelegateFunction();//代理

public SystemLogin()

{

InitializeComponent();

}

private void SystemLogin_Load(object sender, EventArgs e)

{

Thread thread = new Thread(CrossThreadFlush);

thread.IsBackground = true;

thread.Start();

}

private void CrossThreadFlush ()

{

while (true)

{

Thread.Sleep(1000);

ThreadFunction();

}

}

private void ThreadFunction()

{

if (https://www.doczj.com/doc/f310384999.html,bel1.InvokeRequired)//等待异步

{

DelegateFunction df = new DelegateFunction(ThreadFunction);

this.Invoke(df);//通过代理调用刷新方法

}

else

{

https://www.doczj.com/doc/f310384999.html,bel1.Text = DateTime.Now.ToString();

}

}

}

}

我们可以看到问题已经被解决了,通过等待异步,我们就不会总是持有主线程的控制,这样就可以在不发生跨线程调用异常的情况下完成多线程对winform 多线程控件的控制了。

刚运行可执行文件时会先显示Label控件的Text值,大概一秒后就可以看到时间:

图4 图5

解决方案二的优化:

利用了delegate的异步调用。

using System;

using System.Windows.Forms;

using System.Threading;

namespace KingChat

{

public partial class SystemLogin : DevExpress.XtraEditors.XtraForm

{

private delegate void DelegateFunction();//代理

public SystemLogin()

{

InitializeComponent();

}

private void SystemLogin_Load(object sender, EventArgs e)

{

Thread thread = new Thread(CrossThreadFlush);

thread.IsBackground = true;

thread.Start();

}

//线程2的执行方法

private void CrossThreadFlush ()

{

DelegateFunction df = new DelegateFunction(ThreadFunction);

df.BeginInvoke(null, null);

}

//用代理调用主线程的控件

private void ThreadFunction()

{

while (true)

{

https://www.doczj.com/doc/f310384999.html,bel1.Text = DateTime.Now.ToString();

Thread.Sleep(1000);

}

}

}

}

直接运行可执行文件:

图6

用多线程同步方法解决生产者-消费者问题(操作系统课设)

. 题目用多线程同步方法解决生产者-消费 者问题(Producer-Consumer Problem) 学院计算机科学与技术学院 专业软件工程 班级 姓名 指导教师 年月日

目录 目录 (1) 课程设计任务书 (2) 正文 (2) 1.设计目的与要求 (2) 1.1设计目的 (2) 1.2设计要求 (2) 2.设计思想及系统平台 (2) 2.1设计思想 (2) 2.2系统平台及使用语言 (2) 3.详细算法描述 (3) 4.源程序清单 (5) 5.运行结果与运行情况 (10) 6.调试过程 (15) 7.总结 (15) 本科生课程设计成绩评定表 (16)

课程设计任务书 学生姓名:专业班级: 指导教师:工作单位:计算机科学与技术学院 题目: 用多线程同步方法解决生产者-消费者问题 (Producer-Consumer Problem) 初始条件: 1.操作系统:Linux 2.程序设计语言:C语言 3.有界缓冲区内设有20个存储单元,其初值为0。放入/取出的数据项按增序设定为1-20这20个整型数。 要求完成的主要任务:(包括课程设计工作量及其技术要求,以及说明书撰写等具体要 求) 1.技术要求: 1)为每个生产者/消费者产生一个线程,设计正确的同步算法 2)每个生产者和消费者对有界缓冲区进行操作后,即时显示有界缓冲区的当前全部内容、当前指针位置和生产者/消费者线程的自定义标识符。 3)生产者和消费者各有两个以上。 4)多个生产者或多个消费者之间须共享对缓冲区进行操作的函数代码。 2.设计说明书内容要求: 1)设计题目与要求 2)总的设计思想及系统平台、语言、工具等。 3)数据结构与模块说明(功能与流程图) 4)给出用户名、源程序名、目标程序名和源程序及其运行结果。(要注明存储各个程序及其运行结果的主机IP地址和目录。) 5)运行结果与运行情况 (提示: (1)有界缓冲区可用数组实现。 (2)编译命令可用:cc -lpthread -o 目标文件名源文件名 (3)多线程编程方法参见附件。) 3. 调试报告: 1)调试记录 2)自我评析和总结 上机时间安排: 18周一~ 五 08:0 - 12:00 指导教师签名:年月日

4:一个经典的多线程同步问题汇总

一个经典的多线程同步问题 程序描述: 主线程启动10个子线程并将表示子线程序号的变量地址作为参数传递给子线程。子线程接收参数 -> sleep(50) -> 全局变量++ -> sleep(0) -> 输出参数和全局变量。 要求: 1.子线程输出的线程序号不能重复。 2.全局变量的输出必须递增。 下面画了个简单的示意图: 分析下这个问题的考察点,主要考察点有二个: 1.主线程创建子线程并传入一个指向变量地址的指针作参数,由于线程启动须要花费一定的时间,所以在子线程根据这个指针访问并保存数据前,主线程应等待子线程保存完毕后才能改动该参数并启动下一个线程。这涉及到主线程与子线程之间的同步。 2.子线程之间会互斥的改动和输出全局变量。要求全局变量的输出必须递增。这涉及到各子线程间的互斥。 下面列出这个程序的基本框架,可以在此代码基础上进行修改和验证。 //经典线程同步互斥问题 #include #include #include long g_nNum; //全局资源 unsigned int__stdcall Fun(void *pPM); //线程函数 const int THREAD_NUM = 10; //子线程个数 int main() { g_nNum = 0;

HANDLE handle[THREAD_NUM]; int i = 0; while (i < THREAD_NUM) { handle[i] = (HANDLE)_beginthreadex(NULL, 0, Fun, &i, 0, NULL); i++;//等子线程接收到参数时主线程可能改变了这个i的值} //保证子线程已全部运行结束 WaitForMultipleObjects(THREAD_NUM, handle, TRUE, INFINITE); return 0; } unsigned int__stdcall Fun(void *pPM) { //由于创建线程是要一定的开销的,所以新线程并不能第一时间执行到这来int nThreadNum = *(int *)pPM; //子线程获取参数 Sleep(50);//some work should to do g_nNum++; //处理全局资源 Sleep(0);//some work should to do printf("线程编号为%d 全局资源值为%d\n", nThreadNum, g_nNum); return 0; } 运行结果:

四种进程或线程同步互斥的控制方法

四种进程或线程同步互斥的控制方法 1、临界区:通过对多线程的串行化来访问公共资源或一段代码,速度快,适合控制数据访问。 2、互斥量:为协调共同对一个共享资源的单独访问而设计的。 3、信号量:为控制一个具有有限数量用户资源而设计。 4、事件:用来通知线程有一些事件已发生,从而启动后继任务的开始。 一临界区 临界区的使用在线程同步中应该算是比较简单,说它简单还是说它同后面讲到的其它方法相比更容易理解。举个简单的例子:比如说有一个全局变量(公共资源)两个线程都会对它进行写操作和读操作,如果我们在这里不加以控制,会产生意想不到的结果。假设线程A 正在把全局变量加1然后打印在屏幕上,但是这时切换到线程B,线程B又把全局变量加1然后又切换到线程A,这时候线程A打印的结果就不是程序想要的结果,也就产生了错误。解决的办法就是设置一个区域,让线程A在操纵全局变量的时候进行加锁,线程B如果想操纵这个全局变量就要等待线程A释放这个锁,这个也就是临界区的概念。 二互斥体 windows api中提供了一个互斥体,功能上要比临界区强大。也许你要问,这个东东和临界区有什么区别,为什么强大?它们有以下几点不一致: 1.critical section是局部对象,而mutex是核心对象。因此像waitforsingleobject是不可以等待临界区的。 2.critical section是快速高效的,而mutex同其相比要慢很多 3.critical section使用围是单一进程中的各个线程,而mutex由于可以有一个名字,因此它是可以应用于不同的进程,当然也可以应用于同一个进程中的不同线程。 4.critical section 无法检测到是否被某一个线程释放,而mutex在某一个线程结束之后会产生一个abandoned的信息。同时mutex只能被拥有它的线程释放。下面举两个应用mutex 的例子,一个是程序只能运行一个实例,也就是说同一个程序如果已经运行了,就不能再运行了;另一个是关于非常经典的哲学家吃饭问题的例子。 三事件 事件对象的特点是它可以应用在重叠I/O(overlapped I/0)上,比如说socket编程中有两种模型,一种是重叠I/0,一种是完成端口都是可以使用事件同步。它也是核心对象,因此可以被waitforsingleobje这些函数等待;事件可以有名字,因此可以被其他进程开启。 四信号量 semaphore的概念理解起来可能要比mutex还难,我先简单说一下创建信号量的函数,因为我在开始使用的时候没有很快弄清楚,可能现在还有理解不对的地方,如果有错误还是请大侠多多指教。 CreateSemaphore( LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, // SD LONG lInitialCount, // initial count LONG lMaximumCount, // maximum count LPCTSTR lpName // object name )

用多线程同步方法解决生产者-消费者问题(操作系统课设)

用多线程同步方法解决生产者-消费者问题(操作系统课设)

题目 用多线程同步方法解决生产者-消费 者问题(Producer-Consume r Problem) 学院 物理学与电子信息工程学院 专业电子信息工程班级08电信本一班姓名 指导教师 2010 年12 月日

目录 目录 0 课程设计任务书 (1) 正文 (3) 1.设计目的与要求 (3) 1.1设计目的 (3) 1.2设计要求 (3) 2.设计思想及系统平台 (3) 2.1设计思想 (3) 2.2系统平台及使用语言 (3) 3.详细算法描述 (4) 4.源程序清单 (7) 5.运行结果与运行情况 (12) 6.调试过程 (16) 7.总结 (16)

课程设计任务书 题目: 用多线程同步方法解决生产者-消费者问题 (Producer-Consumer Problem) 初始条件: 1.操作系统:Linux 2.程序设计语言:C语言 3.有界缓冲区内设有20个存储单元,其初 值为0。放入/取出的数据项按增序设定为 1-20这20个整型数。 要求完成的主要任务:(包括课程设计工作量及其技术要求,以及说明书撰写等具体要求) 1.技术要求: 1)为每个生产者/消费者产生一个线程,设计正确的同步算法 2)每个生产者和消费者对有界缓冲区进行操作后,即时显示有界缓冲区的当前全部 内容、当前指针位置和生产者/消费者

线程的自定义标识符。 3)生产者和消费者各有两个以上。 4)多个生产者或多个消费者之间须共享对缓冲区进行操作的函数代码。 2.设计说明书内容要求: 1)设计题目与要求 2)总的设计思想及系统平台、语言、工具 等。 3)数据结构与模块说明(功能与流程图) 4)给出用户名、源程序名、目标程序名和源程序及其运行结果。(要注明存储各个 程序及其运行结果的主机IP地址和目 录。) 5)运行结果与运行情况 (提示: (1)有界缓冲区可用数组实现。 (2)编译命令可用:cc -lpthread -o 目标文件名源文件名 (3)多线程编程方法参见附件。) 3. 调试报告: 1)调试记录 2)自我评析和总结

多线程同步方法及比较

多线程同步方法及比较 多线程同步方法: 1.临界区:通过对多线程的串行化来访问公共资源或一段代码,速度快,适合控制数 据访问。. 2.互斥量:为协调一起对一个共享资源的单独访问而设计的。. 3.信号量:为控制一个具备有限数量用户资源而设计。. 4.事件:用来通知线程有一些事件已发生,从而启动后继任务的开始。 临界区(Critical Section).. 确保在某一时刻只有一个线程能访问数据的简便办法。在任意时刻只允许一个线程对共享资源进行访问。假如有多个线程试图同时访问临界区,那么在有一个线程进入后其他任何试图访问此临界区的线程将被挂起,并一直持续到进入临界区的线程离开。临界区在被释放后,其他线程能够继续抢占,并以此达到用原子方式操作共享资源的目的。 临界区包含两个操作原语: EnterCriticalSection()进入临界区 LeaveCriticalSection()离开临界区。 EnterCriticalSection()语句执行后代码将进入临界区以后无论发生什么,必须确保和之匹配的LeaveCriticalSection()都能够被执行到。否则临界区保护的共享资源将永远不会被释放。虽然临界区同步速度很快,但却只能用来同步本进程内的线程,而不可用来同步多个进程中的线程。 MFC为临界区提供有一个CCriticalSection类,使用该类进行线程同步处理是很简单的。只需在线程函数中用CCriticalSection类成员函数Lock()和UnLock()标定出被保护代码片段即可。Lock()后代码用到的资源自动被视为临界区内的资源被保护。UnLock后别的线程才能访问这些资源。. ------------------------------------------------

用多线程同步方法解决生产者-消费者问题

目录 1.需求分析 (1) 1.1 课程设计题目 (1) 1.2 课程设计任务 (1) 1.3 课程设计原理 (1) 1.4 课程设计要求 (1) 1.5 实验环境 (1) 2. 概要设计 (2) 2.1 课程设计方案概述 (2) 2.2 课程设计流程图 (2) 3.详细设计 (3) 3.1 主程序模块 (3) 3.2 生产者程序模块 (4) 3.3 消费者程序模块 (5) 4.调试中遇到的问题及解决方案 (5) 5.运行结果 (6) 6.实验小结 (7) 参考文献 (7) 附录:源程序清单 (7)

1.需求分析 1.1 课程设计题目 用多线程同步方法解决生产者-消费者问题 1.2 课程设计任务 (1)每个生产者和消费者对有界缓冲区进行操作后,即时显示有界缓冲区的全部内容、 当前指针位置和生产者/消费者线程的标识符。 (2)生产者和消费者各有两个以上。 (3)多个生产者或多个消费者之间须共享对缓冲区进行操作的函数代码。 1.3 课程设计原理 生产者和消费者问题是从操作系统中的许多实际同步问题中抽象出来的具有代表性的问题,它反映了操作系统中典型的同步例子,生产者进程(进程由多个线程组成)生产信息,消费者进程使用信息,由于生产者和消费者彼此独立,且运行速度不确定,所以很可能出现生产者已产生了信息而消费者却没有来得及接受信息这种情况。为此,需要引入由一个或者若干个存储单元组成的临时存储区(即缓冲区),以便存放生产者所产生的信息,解决平滑进程间由于速度不确定所带来的问题。 1.4 课程设计要求 (1)有界缓冲区内设有20个存储单元,放入/取出的数据项设定为1~20这20个整型数。 (2)每个生产者和消费者对有界缓冲区进行操作后,即时显示有界缓冲区的全部内容、 当前指针位置和生产者/消费者线程的标识符。 (3)生产者和消费者各有两个以上。 (4)多个生产者或多个消费者之间须共享对缓冲区进行操作的函数代码。 1.5 实验环境 系统平台:LINUX 开发语言:C 开发工具:PC机一台

多线程同步

一、教学导入 复习线程的生命周期及状态转换的概念, ?引入新课。 生活中的事例1:购买火车票,两个人同时买最后一张火车票; 生活中的事例2:支付款项,支付业务可以在不同的地方同时进行。 ?以上会发生线程安全问题,引入多线程同步问题。 二、讲授新课 1.线程安全问题 模拟窗口售票程序,售票的动作需要同时执行,所以使用多线程技术。假如共有100张票出售,并在售票的代码中每次售票时线程休眠10毫秒,如下所示 Example1.java。 public class Example11 { public static void main(String[] args) { // 创建Ticket1 对象 SaleThreadsaleThread = new SaleThread(); // 创建并开启四个线程 new Thread(saleThread, "线程一").start(); new Thread(saleThread, "线程二").start(); new Thread(saleThread, "线程三").start(); new Thread(saleThread, "线程四").start(); } } // 定义Ticket1类实现Runnable接口

class SaleThread implements Runnable { //1,描述票的数量。 private int tickets = 100; // 100张票 //2,售票的动作,这个动作需要被多线程执行,那就是线程任务代码。需要定义run方法中。 //线程任务中通常都有循环结构。 public void run() { while (tickets > 0) { try { Thread.sleep(10); //要让线程在这里稍停,模拟问题的发生。sleep 看到了0 -1 -2 错误的数据,这就是传说中的多线程安全问题。经过此处的线程休眠10毫秒 } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "---卖出的票"+ tickets--);//打印线程名称 } } } 运行结果如下图所示。 从上图可以看出,售出的票出现了0、-1、-2这样的票号,这种现象是不应该出现的,因此,上面的多线程程序存在安全问题。 【问题产生的原因】 1,线程任务中在操作共享的数据。 2,线程任务操作共享数据的代码有多条(运算有多个)。 【解决思路】

Windows中线程间同步的方法

Windows中线程间同步的方法主要有:事件(Event)、临界区(Critical Section)、互斥量(Mutex)和信号灯(Semaphore)。 1)使用事件对象进行线程间同步: 在使用CreateEvent函数创建事件对象时,将bManualReset参数设置为FALSE,然后在需要独占操作的代码前面加上一个WaitForSingleObject函数,后面加上一个SetEvent即可。 由于bManualReset参数为FALSE,这样当某个线程等待到Event后,Event对象的状态马上就变为复位状态,这样其他线程执行到WaitForSingleObject时就全部处于等待中了,当活动的线程操作完毕后,执行SetEvent函数,Event对象的状态才恢复到置位,这样其他等待的线程才会有一个能继续操作。 SetEvent函数原型如下: HANDLE WINAPI CreateEvent( __in_opt LPSECURITY_ATTRIBUTES lpEventAttributes, //安全描述符 __in BOOL bManualReset, //指定事件对象是否需要手动复位 __in BOOL bInitialState, //指定事件对象创建时的初始状态,为TRUE表示初始状态是置位状态; //为FALSE表示初始状态是复位状态 __in_opt LPCTSTR lpName //指定事件对象名称 ); 当一个事件被创建后,程序就可以通过SetEvent和ResetEvent函数来设置事件的状态:BOOL WINAPI SetEvent( __in HANDLE hEvent ); BOOL WINAPI ResetEvent(

JAVA中的同步与异步问题 线程和线程池的重要知识

java线程同步与异步线程池 java线程同步与异步线程池 1)多线程并发时,多个线程同时请求同一个资源,必然导致此资源的数据不安全,A线程修改了B线 程的处理的数据,而B线程又修改了A线程处理的数理。显然这是由于全局资源造成的,有时为了解 决此问题,优先考虑使用局部变量,退而求其次使用同步代码块,出于这样的安全考虑就必须牺牲 系统处理性能,加在多线程并发时资源挣夺最激烈的地方,这就实现了线程的同步机制同步:A线程要请求某个资源,但是此资源正在被B线程使用中,因为同步机制存在,A线程请求 不到,怎么办,A线程只能等待下去 异步:A线程要请求某个资源,但是此资源正在被B线程使用中,因为没有同步机制存在,A线程 仍然请求的到,A线程无需等待

显然,同步最最安全,最保险的。而异步不安全,容易导致死锁,这样一个线程死掉就会导致整个 进程崩溃,但没有同步机制的存在,性能会有所提升 java中实现多线程 1)继承Thread,重写里面的run方法 2)实现runnable接口 Doug Lea比较推荐后者,第一,java没有单继承的限制第二,还可以隔离代码 线程池 要知道在计算机中任何资源的创建,包括线程,都需要消耗系统资源的。在WEB服务中,对于web服 务器的响应速度必须要尽可能的快,这就容不得每次在用户提交请求按钮后,再创建线程提供服务 。为了减少用户的等待时间,线程必须预先创建,放在线程池中,线程池可以用HashTable这种数

据结构来实现,看了Apach HTTP服务器的线程池的源代码,用是就是HashTable,KEY 用线程对象, value用ControlRunnable,ControlRunnable是线程池中唯一能干活的线程,是它指派线程池中的 线程对外提供服务。 出于安全考虑,Apach HTTP服务器的线程池它是同步的。听说weblogic有异步的实现方式,没有研 究过,不敢确定 --------------------------------------------------------------------------------------- --------------------------------------------------------------------------------------一、关键字: thread(线程)、thread-safe(线程安全)、intercurrent(并发的) synchronized(同步的)、asynchronized(异步的)、 volatile(易变的)、atomic(原子的)、share(共享) 二、总结背景: 一次读写共享文件编写,嚯,好家伙,竟然揪出这些零碎而又是一路的知识点。于是乎,

同步多线程-(SMT)-技术基础

同步多线程(SMT) 技术基础 介绍 微处理器设计的发展和我们对速度的需求,诞生了很多新技术并使它们迅速发展,也使现在的以及下一代的处理器的效率和性能都有了提升。一定的体系结构下,在提高性能、降低开销和指令级并行性(ILP之间)加以平衡,可以降低平均CPI。 同步多线程技术(SMT)是一种体系结构模型,其目的是在现有硬件条件下,通过提高计算能力来提高处理器的性能。因此,同步多线程技术结合了多重启动处理器(超标量和VLIW)和多线程处理器的思想来增加并行度,进而提高性能。 多重启动处理器可以在一个周期内执行多条(2,4甚至8条)指令,而多线程和多处理器(SMP和CMP)结构可以同时或者在很少的延迟内执行来自不同线程的指令。SMT结构中,不仅在一周期内启动多条指令,而且也能在同一周期内启动来自相互独立的线程(或上下文)的指令。在理论上,这种改进运用了指令级并行性(ILP)和线程级并行性(TLP)技术来提高执行功能单元的效率。 同步多线程技术之前的研究 多重启动处理器(Multiple Issue Processors) 运用在超标量和VLIW上的多重启动处理器,其目的是为了降低平均CPI,通过在一个周期内启动多条指令,充分利用处理器的功能单元。要想有效利用多重启动处理器资源的关键就是在运行的程序中,发现足够的指令级并行性,通常这种并行性是由硬件决定的。超长指令字(VLIW)处理器每周期启动固定数目的操作,而这些操作是由编译器决定的。 超标量处理器通常是指“动态调度”(dynamically scheduled)的多重启动处理器,因为他们是通过硬件来发现代码中的并行性。不同的是,VLIW处理器通常是“静态调度”(statically scheduled)的,因为他们依靠编译器来发现并优化指令级并行性。 无论是动态或是静态调度,如何有效利用多重启动处理器,依赖于发现并利用指令级并行性。指令级并行性来自同一个上下文环境、程序或线程。CPU和编译器重新安排和启动指令,以此来最大限度的利用资源而不改变应用程序的完整性。在多重启动处理器中,如果不能发现足够的并行指令来填满发射槽(issue slot),那么资源就被浪费了。 超标量处理器现在大致有DEC/Compaq 21164, PowerPC, MIPS R10000, Sun UltraSparc 和 Hewlett Packard PA-8000。而VLIW处理器则包括Intel IA-64 (Itanium) 和Transmeta Crusoe。对多重启动处理器和使用记分牌(scoreboarding)和Tomasulo算法的动态调度已经有了很多研究,我将不再花费时间分析他们。 多线程处理器(Multithreaded Processors) 多线程处理器主要通过降低操作延迟以提高处理器的效率,比如说cache失效和需要长执行周期的指令。一个多线程处理器通过分配给每个线程独立的PC(program counter)和寄存器来保持线程间相互独立的状态。由于每个处理器在切换上下文时几乎没有延迟,所以每个周期可以启动来自不同线程的指令。如果处理器在每个周期切换上下文,这就叫做细颗粒(fine-grained)的多线程或交叉(interleaving)。粗颗粒(Course grain)的多线程处理器则是在某一线程出现长延迟时,才切换线程,以保证指令的持续启动。正是由于存在分离的、独立的上下文和指令资源,多线程体系结构才能利用线程级并行性(TLP),从而提高处理器的效率。多线程处理器通过比传统处理器更精细地共享处理器资源,从而

linux下多线程同步的方式

Linux下提供了多种方式来处理线程同步,最常用的是互斥锁、条件变量和信号量。 一、互斥锁(mutex) 锁机制是同一时刻只允许一个线程执行一个关键部分的代码。 1. 初始化锁 int pthread_mutex_init(pthread_mutex_t *mutex,const pthread_mutex_attr_t *mutexattr); 其中参数mutexattr 用于指定锁的属性(见下),如果为NULL则使用缺省属性。 互斥锁的属性在创建锁的时候指定,在LinuxThreads实现中仅有一个锁类型属性,不同的锁类型在试图对一个已经被锁定的互斥锁加锁时表现不同。当前有四个值可供选择:(1)PTHREAD_MUTEX_TIMED_NP,这是缺省值,也就是普通锁。当一个线程加锁以后,其余请求锁的线程将形成一个等待队列,并在解锁后按优先级获得锁。这种锁策略保证了资源分配的公平性。 (2)PTHREAD_MUTEX_RECURSIVE_NP,嵌套锁,允许同一个线程对同一个锁成功获得多次,并通过多次unlock解锁。如果是不同线程请求,则在加锁线程解锁时重新竞争。(3)PTHREAD_MUTEX_ERRORCHECK_NP,检错锁,如果同一个线程请求同一个锁,则返回EDEADLK,否则与PTHREAD_MUTEX_TIMED_NP类型动作相同。这样就保证当不允许多次加锁时不会出现最简单情况下的死锁。 (4)PTHREAD_MUTEX_ADAPTIVE_NP,适应锁,动作最简单的锁类型,仅等待解锁后重新竞争。 2. 阻塞加锁 int pthread_mutex_lock(pthread_mutex *mutex); 3. 非阻塞加锁 int pthread_mutex_trylock( pthread_mutex_t *mutex); 该函数语义与pthread_mutex_lock() 类似,不同的是在锁已经被占据时返回EBUSY 而不是挂起等待。 4. 解锁(要求锁是lock状态,并且由加锁线程解锁) int pthread_mutex_unlock(pthread_mutex *mutex); 5. 销毁锁(此时锁必需unlock状态,否则返回EBUSY) int pthread_mutex_destroy(pthread_mutex *mutex); 示例代码: [oracle@localhost]$ cat mutextest.c

线程同步机制实验报告

线程同步机制实验报告

一、实验目的: 通过观察共享数据资源但不受控制的两个线程的并发运行输出结果,体会同步机制的必要性和重要性。然后利用现有操作系统提供的同步机制编程实现关于该两个线程的有序控制,同时要求根据同步机制的Peterson软件解决方案尝试自己编程实现同步机制和用于同一问题的解决,并基于程序运行时间长短比较两种同步机制。 二、实验内容: 1、基于给定银行账户间转账操作模拟代码作为线程执行代码,在主线程中 创建两个并发线程,编程实现并观察程序运行结果和予以解释说明。(无 同步机制) 2、利用Win32 API中互斥信号量操作函数解决上述线程并发问题,并分析、 尝试和讨论线程执行体中有关信号量操作函数调用的正确位置。 3、根据同步机制的Peterson软件解决方案尝试自己编程实现线程同步机制 和用于上述线程并发问题的解决,并基于程序运行时间长短将其与基于 Win32 API互斥信号量的线程同步机制的效率展开比较。其间,可规定线 程主体代码循环执行1000000次。 三、实验环境: 操作系统:Windows 7 软件:VC++ 四、实验设计: 本实验包含三个基于并发线程的程序,第一个没有同步机制,第二个利 用Win32 API中互斥信号量操作函数解决线程并发问题,第三个根据同 步机制的Peterson软件解决方案实现线程同步机制并解决线程并发问 题。三个程序拥有相同的线程主体: 线程主体设计: do{ nTemp1 = nAccount1; nTemp2 = nAccount2; nRandom = rand(); nAccount1 = nTemp1 + nRandom; nAccount2 = nTemp2 - nRandom; nLoop++; } while ((nAccount1 + nAccount2)==0); 该线程主体是对银行账户间转账操作模拟的模拟,可知,若并发的

Windows的多线程同步实验报告

一、实验目的 在掌握基于消息的windows程序结构和多线程程序设计方法的基础上,设计一个多线程同步的程序。使学生能够从程序设计的角度了解多线程程序设计的方法和在windows系统下多线程同步互斥的机制。 二、实验内容 1.理解Windows程序设计的基本思想,理解基于消息的程序设计方法,能够设计出简单的基于事件的windows程序,完成基本控件的使用 2.结合操作系统中信号量与互斥体的概念,在MFC中找到对应的相关类 3.设计一个多线程同步的程序, 多线程概述 进程和线程都是操作系统的概念。进程是应用程序的执行实例,每个进程是由私有的虚拟地址空间、代码、数据和其它各种系统资源组成,进程在运行过程中创建的资源随着进程的终止而被销毁,所使用的系统资源在进程终止时被释放或关闭。 线程是进程内部的一个执行单元。系统创建好进程后,实际上就启动执行了该进程的主执行线程,主执行线程以函数地址形式,比如说main或WinMain函数,将程序的启动点提供给Windows系统。主执行线程终止了,进程也就随之终止。 每一个进程至少有一个主执行线程,它无需由用户去主动创建,是由系统自动创建的。用户根据需要在应用程序中创建其它线程,多个线程并发地运行于同一个进程中。一个进程中的所有线程都在该进程的虚拟地址空间中,共同使用这些虚拟地址空间、全局变量和系统资源,所以线程间的通讯非常方便,多线程技术的应用也较为广泛。 多线程可以实现并行处理,避免了某项任务长时间占用CPU时间。要说明的一点是,目前大多数的计算机都是单处理器(CPU)的,为了运行所有这些线程,操作系统为每个独立线程安排一些CPU时间,操作系统以轮换方式向线程提供时间片,这就给人一种假象,好象这些线程都在同时运行。由此可见,如果两个非常活跃的线程为了抢夺对CPU的控制权,在线程切换时会消耗很多的CPU资源,反而会降低系统的性能。这一点在多线程编程时应该注意。 Win32 SDK函数支持进行多线程的程序设计,并提供了操作系统原理中的各种同步、互斥和临界区等操作。Visual C++ 6.0中,使用MFC类库也实现了多线程的程序设计,使得多线程编程更加方便。 VC中提供线程同步的方法: 临界区(CCriticalSection) 事件(CEvent) 互斥量(CMutex)

用多线程同步方法解决生产者-消费者问题操作系统课设

学号: 课程设计 题目用多线程同步方法解决生产者-消费 者问题(Producer-Consumer Problem) 学院计算机科学与技术学院 专业软件工程 班级 姓名 指导教师 年月日

目录 目录 (1) 课程设计任务书 (1) 正文 (2) 1.设计目的与要求 (2) 1.1设计目的 (2) 1.2设计要求 (2) 2.设计思想及系统平台 (2) 2.1设计思想 (2) 2.2系统平台及使用语言 (2) 3.详细算法描述 (3) 4.源程序清单 (5) 5.运行结果与运行情况 (10) 6.调试过程 (13) 7.总结 (13) 本科生课程设计成绩评定表 ..................................................... 错误!未定义书签。 课程设计任务书 学生姓名:专业班级: 指导教师:工作单位:计算机科学与技术学院 题目: 用多线程同步方法解决生产者-消费者问题(Producer-Consumer Problem) 初始条件: 1.操作系统:Linux 2.程序设计语言:C语言 3.有界缓冲区内设有20个存储单元,其初值为0。放入/取出的数据项按增序设定为1-20这20个整型数。 要求完成的主要任务:(包括课程设计工作量及其技术要求,以及说明书撰写等具体要 求) 1.技术要求:

1)为每个生产者/消费者产生一个线程,设计正确的同步算法 2)每个生产者和消费者对有界缓冲区进行操作后,即时显示有界缓冲区的当前全部内容、当前指针位置和生产者/消费者线程的自定义标识符。 3)生产者和消费者各有两个以上。 4)多个生产者或多个消费者之间须共享对缓冲区进行操作的函数代码。 2.设计说明书内容要求: 1)设计题目与要求 2)总的设计思想及系统平台、语言、工具等。 3)数据结构与模块说明(功能与流程图) 4)给出用户名、源程序名、目标程序名和源程序及其运行结果。(要注明存储各个程序及其运行结果的主机IP地址和目录。) 5)运行结果与运行情况 (提示: (1)有界缓冲区可用数组实现。 (2)编译命令可用:cc -lpthread -o 目标文件名源文件名 (3)多线程编程方法参见附件。) 3. 调试报告: 1)调试记录 2)自我评析和总结 上机时间安排: 18周一~ 五 08:0 - 12:00 指导教师签名:年月日 系主任(或责任教师)签名:年月日

线程同步机制实验报告

线程同步机制 实验报告 一、实验目的: 通过观察共享数据资源但不受控制的两个线程的并发运行输出结果,体会同步机制的必要性和重要性。然后利用现有操作系统提供的同步机制编程实现

关于该两个线程的有序控制,同时要求根据同步机制的Peterson软件解决方案尝试自己编程实现同步机制和用于同一问题的解决,并基于程序运行时间长短比较两种同步机制。 二、实验容: 1、基于给定银行账户间转账操作模拟代码作为线程执行代码,在主线程中 创建两个并发线程,编程实现并观察程序运行结果和予以解释说明。(无 同步机制) 2、利用Win32 API中互斥信号量操作函数解决上述线程并发问题,并分析、 尝试和讨论线程执行体中有关信号量操作函数调用的正确位置。 3、根据同步机制的Peterson软件解决方案尝试自己编程实现线程同步机制 和用于上述线程并发问题的解决,并基于程序运行时间长短将其与基于 Win32 API互斥信号量的线程同步机制的效率展开比较。其间,可规定线 程主体代码循环执行1000000次。 三、实验环境: 操作系统:Windows 7 软件:VC++6.0 四、实验设计: 本实验包含三个基于并发线程的程序,第一个没有同步机制,第二个利用Win32 API中互斥信号量操作函数解决线程并发问题,第三个根据同 步机制的Peterson软件解决方案实现线程同步机制并解决线程并发问 题。三个程序拥有相同的线程主体: 线程主体设计: do{ nTemp1 = nAccount1; nTemp2 = nAccount2; nRandom = rand(); nAccount1 = nTemp1 + nRandom; nAccount2 = nTemp2 - nRandom; nLoop++; } while ((nAccount1 + nAccount2)==0); 该线程主体是对银行账户间转账操作模拟的模拟,可知,若并发的线程不发生交叉,则依次转账操作后nAccount1 + nAccount2的值永远 为0,程序不会跳出循环,如果线程发生交叉,则经过若干次转账操作 后,就有可能出现nAccount1 + nAccount2不为0的情况,此时程序跳 出循环。本实验的三个程序就是基于此线程主体逐步实现的。

关于线程同步(5种同步方式)

Java笔记--关于线程同步(5种同步方式) 为何要使用同步? java允许多线程并发控制,当多个线程同时操作一个可共享的资源变量时(如数据的增删改查), 将会导致数据不准确,相互之间产生冲突,因此加入同步锁以避免在该线程没有完成操作之前,被其他线程的调用, 从而保证了该变量的唯一性和准确性。 1.同步方法 即有synchronized关键字修饰的方法。 由于java的每个对象都有一个内置锁,当用此关键字修饰方法时, 内置锁会保护整个方法。在调用该方法前,需要获得内置锁,否则就处于阻塞状态。 代码如: public synchronized void save(){} 注: synchronized关键字也可以修饰静态方法,此时如果调用该静态方法,将会锁住整个类 2.同步代码块 即有synchronized关键字修饰的语句块。 被该关键字修饰的语句块会自动被加上内置锁,从而实现同步 代码如: synchronized(object){ } 注:同步是一种高开销的操作,因此应该尽量减少同步的内容。 通常没有必要同步整个方法,使用synchronized代码块同步关键代码即可。 代码实例:

package com.xhj.thread; /** * 线程同步的运用 * * @author XIEHEJUN * */ public class SynchronizedThread { class Bank { private int account = 100; public int getAccount() { return account; } /** * 用同步方法实现 * * @param money */ public synchronized void save(int money) { account += money; } /** * 用同步代码块实现 * * @param money */ public void save1(int money) {

多线程同步的三种方式 Linux

多线程同步的三种?方式: Linux 线程同步有最常?用的是:互斥锁、条件变量量和信号量量。?一、通过锁机制实现线程间的同步。初始化锁。在Linux下,线程的互斥量量数据类型是pthread_mutex_t。在使?用前,要对它进?行行初始化。静态分配:pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; 动态分配:int pthread_mutex_init(pthread_mutex_t mutex, const pthreadmutexattr_t mutexattr); 加锁。对共享资源的访问,要对互斥量量进?行行加锁,如果互斥量量已经上了了锁,调?用线程会阻塞,直到互斥量量被解锁。 int pthread_mutex_lock(pthread_mutex mutex); int pthread_mutex_trylock(pthread_mutex_t mutex);解锁。在完成了了对共享资源的访问后,要对互斥量量进?行行解锁。 int pthread_mutex_unlock(pthread_mutex_t mutex);销毁锁。锁在是使?用完成后,需要进?行行销毁以释放资源。 int pthread_mutex_destroy(pthread_mutex mutex); ?二、条件变量量(cond) 与互斥锁不不同,条件变量量是?用来等待?而不不是?用来上锁的。条件变量量?用来?自动阻塞?一个线程,直到某特殊情况发?生为?止。通常条件变量量和互斥锁同时使?用。条件变量量分为两部分: 条件和变量量。条件本身是由互斥量量保护的。线程在改变条件状态前先要锁住互斥量量。条件变量量使我们可以睡眠等待某种条件出现。条件变量量是利利?用线程间共享的全局变量量进?行行同步的?一种机制,主要包括两个动作:?一个线程等待"条件变量量的条件成?立"?而挂起;另?一个线程使"条件成?立"(给出条件成?立信号)。条件的检测是在互斥锁的保护下进?行行的。如果?一个条件为假,?一个线程?自动阻塞,并释放等待状态改变的互斥锁。如果另?一个线程改变了了条件,它发信号给关联的条件变量量,唤醒?一个或多个等待它的线程,重新获得互斥锁,重新评价条件。如果两进程共享可读写的内存,条件变量量可以被?用来实现这两进程间的线程同步。初始化条件变量量。静态态初始化,pthread_cond_t cond = PTHREAD_COND_INITIALIER; 动态初始化,int pthread_cond_init(pthread_cond_t cond, pthreadcondattrt cond_attr); 等待条件成?立。释放锁,同时阻塞等待条件变量量为真才?行行。timewait()设置等待时间,仍未signal,返回ETIMEOUT(加锁保证只有?一个线程wait) int pthread_cond_wait(pthread_cond_t cond, pthreadmutext mutex); int pthread_cond_timewait(pthread_cond_t cond,pthread_mutex mutex,const timespec abstime);激活条件变量量。 pthread_cond_signal,pthread_cond_broadcast(激活所有等待线程) int pthread_cond_signal(pthread_cond_t cond); int

VC60做的实现线程同步的四种方法的详细操作步骤

VC6.0做的实现线程同步的四种方法的详细操作步骤 软件作业一:如何实现线程同步?(二是一个基于单个文档的MFC程序,参考的是某本书上完整的一个可运行实例,所用代码和课件上几乎相同,应该会更符合老师上课讲的思路)windows系统提供的4种同步化机制分别为: 临界区 信号量内核对象 事件内核对象 互斥体对象 一:非MFC下实现线程同步实例 临界区:课本P43、44 // CriticalSection.cpp文件 #include #include #include BOOL g_bContinue = TRUE; int g_nCount1 = 0; int g_nCount2 = 0; CRITICAL_SECTION g_cs; // 对存在同步问题的代码段使用临界区对象 UINT __stdcall ThreadFunc(LPVOID); int main(int argc, char* argv[]) { UINT uId; HANDLE h[2]; // 初始化临界区对象 ::InitializeCriticalSection(&g_cs); h[0] = (HANDLE)::_beginthreadex(NULL, 0, ThreadFunc, NULL, 0, &uId); h[1] = (HANDLE)::_beginthreadex(NULL, 0, ThreadFunc, NULL, 0, &uId); // 等待1秒后通知两个计数线程结束,关闭句柄 Sleep(1000); g_bContinue = FALSE; ::WaitForMultipleObjects(2, h, TRUE, INFINITE); ::CloseHandle(h[0]); ::CloseHandle(h[1]); // 删除临界区对象 ::DeleteCriticalSection(&g_cs);

相关主题
文本预览
相关文档 最新文档