线程指南

线程指南
线程指南

使用条件变量

本节介绍如何使用条件变量。表 4–6 列出了可用的函数。

表 4–6 条件变量函数操作

相关函数说明

初始化条件变量

pthread_cond_init 语法

基于条件变量阻塞

pthread_cond_wait 语法

解除阻塞特定线程

pthread_cond_signal 语法

在指定的时间之前阻塞

pthread_cond_timedwait 语法

在指定的时间间隔内阻塞

pthread_cond_reltimedwait_np 语法

解除阻塞所有线程

pthread_cond_broadcast 语法

销毁条件变量状态

pthread_cond_destroy 语法

初始化条件变量

使用 pthread_cond_init(3C) 可以将 cv 所指示的条件变量初始化为其缺省值,或者指定已经使用 pthread_condattr_init() 设置的条件变量属性。

pthread_cond_init 语法

int pthread_cond_init(pthread_cond_t *cv,

const pthread_condattr_t *cattr);#include

pthread_cond_t cv;

pthread_condattr_t cattr;

/* initialize a condition variable to its default value */

ret = pthread_cond_init(&cv, NULL);

/* initialize a condition variable */

ret = pthread_cond_init(&cv, &cattr); cattr 设置为 NULL。将 cattr 设置为 NULL 与传递缺省条件变量属性对象的地址等效,但是没有内存开销。对于 Solaris 线程,请参见cond_init 语法。

使用 PTHREAD_COND_INITIALIZER 宏可以将以静态方式定义的条件变量初始化为其缺省属性。PTHREAD_COND_INITIALIZER 宏与动态分配具有 null 属性的 pthread_cond_init() 等效,但是不进行错误检查。

多个线程决不能同时初始化或重新初始化同一个条件变量。如果要重新初始化或销毁某个条件变量,则应用程序必须确保该条件变量未被使用。

pthread_cond_init 返回值

pthread_cond_init() 在成功完成之后会返回零。其他任何返回值都表示出现了错误。如果出现以下任一情况,该函数将失败并返回对应的值。

EINVAL

描述:

cattr 指定的值无效。

EBUSY

描述:

条件变量处于使用状态。

EAGAIN

描述:

必要的资源不可用。

ENOMEM

内存不足,无法初始化条件变量。

基于条件变量阻塞

使用 pthread_cond_wait(3C) 可以以原子方式释放 mp 所指向的互斥锁,并导致调用线程基于 cv 所指向的条件变量阻塞。对于 Solaris 线程,请参见cond_wait 语法。

pthread_cond_wait 语法

int pthread_cond_wait(pthread_cond_t *cv,pthread_mutex_t *mutex);#include

pthread_cond_t cv;

pthread_mutex_t mp;

int ret;

/* wait on condition variable */

ret = pthread_cond_wait(&cv, &mp); 阻塞的线程可以通过 pthread_cond_signal() 或pthread_cond_broadcast() 唤醒,也可以在信号传送将其中断时唤醒。

不能通过 pthread_cond_wait() 的返回值来推断与条件变量相关联的条件的值的任何变化。必须重新评估此类条件。

pthread_cond_wait() 例程每次返回结果时调用线程都会锁定并且拥有互斥锁,即使返回错误时也是如此。

该条件获得信号之前,该函数一直被阻塞。该函数会在被阻塞之前以原子方式释放相关的互斥锁,并在返回之前以原子方式再次获取该互斥锁。

通常,对条件表达式的评估是在互斥锁的保护下进行的。如果条件表达式为假,线程会基于条件变量阻塞。然后,当该线程更改条件值时,另一个线程会针对条件变量发出信号。这种变化会导致所有等待该条件的线程解除阻塞并尝试再次获取互斥锁。

必须重新测试导致等待的条件,然后才能从 pthread_cond_wait() 处继续执行。唤醒的线程重新获取互斥锁并从 pthread_cond_wait() 返回之前,条件可能会发生变化。等待线程可能并未真正唤醒。建议使用的测试方法是,将条件检查编写为调用 pthread_cond_wait() 的while() 循环。

pthread_mutex_lock();

while(condition_is_false)

pthread_cond_wait();

pthread_mutex_unlock();如果有多个线程基于该条件变量阻塞,则无法保证按特定的顺序获取互斥锁。

-------------------------------------------------------------------------------- 注–

pthread_cond_wait() 是取消点。如果取消处于暂挂状态,并且调用线程启用了取消功能,则该线程会终止,并在继续持有该锁的情况下开始执行清除处理程序。

--------------------------------------------------------------------------------

pthread_cond_wait 返回值

pthread_cond_wait() 在成功完成之后会返回零。其他任何返回值都表示出现了错误。如果出现以下情况,该函数将失败并返回对应的值。

EINVAL

描述:

cv 或 mp 指定的值无效。

解除阻塞一个线程

对于基于 cv 所指向的条件变量阻塞的线程,使用 pthread_cond_signal(3C) 可以解除阻塞该线程。对于 Solaris 线程,请参见cond_signal 语法。

pthread_cond_signal 语法

int pthread_cond_signal(pthread_cond_t *cv);#include

pthread_cond_t cv;

int ret;

/* one condition variable is signaled */

ret = pthread_cond_signal(&cv); 应在互斥锁的保护下修改相关条件,该互斥锁用于获得信号的条件变量中。否则,可能在条件变量的测试和 pthread_cond_wait() 阻塞之间修改该变量,这会导致无限期等待。

调度策略可确定唤醒阻塞线程的顺序。对于 SCHED_OTHER,将按优先级顺序唤醒线程。

如果没有任何线程基于条件变量阻塞,则调用 pthread_cond_signal() 不起作用。

--------------------------------------------------------------------------------

示例 4–8 使用 pthread_cond_wait() 和 pthread_cond_signal()

pthread_mutex_t count_lock;

pthread_cond_t count_nonzero;

unsigned count;

decrement_count()

{

pthread_mutex_lock(&count_lock);

while (count == 0)

pthread_cond_wait(&count_nonzero, &count_lock);

count = count - 1;

pthread_mutex_unlock(&count_lock);

}

increment_count()

{

pthread_mutex_lock(&count_lock);

if (count == 0)

pthread_cond_signal(&count_nonzero);

count = count + 1;

pthread_mutex_unlock(&count_lock);

}

--------------------------------------------------------------------------------

pthread_cond_signal 返回值

pthread_cond_signal() 在成功完成之后会返回零。其他任何返回值都表示出现了错误。如果出现以下情况,该函数将失败并返回对应的值。

EINVAL

描述:

cv 指向的地址非法。

示例 4–8 说明了如何使用 pthread_cond_wait() 和 pthread_cond_signal()。

在指定的时间之前阻塞

pthread_cond_timedwait(3C) 的用法与 pthread_cond_wait() 的用法基本相同,区别在于在由 abstime 指定的时间之后 pthread_cond_timedwait() 不再被阻塞。

pthread_cond_timedwait 语法

int pthread_cond_timedwait(pthread_cond_t *cv,

pthread_mutex_t *mp, const struct timespec *abstime);#include

#include

pthread_cond_t cv;

pthread_mutex_t mp;

timestruct_t abstime;

int ret;

/* wait on condition variable */

ret = pthread_cond_timedwait(&cv, &mp, &abstime); pthread_cond_timewait() 每次返回时调用线程都会锁定并且拥有互斥锁,即使 pthread_cond_timedwait() 返回错误时也是如此。对于 Solaris 线程,请参见cond_timedwait 语法。

pthread_cond_timedwait() 函数会一直阻塞,直到该条件获得信号,或者最后一个参数所指定的时间已过为止。

-------------------------------------------------------------------------------- 注–

pthread_cond_timedwait() 也是取消点。

-------------------------------------------------------------------------------- -------------------------------------------------------------------------------- 示例 4–9 计时条件等待

pthread_timestruc_t to;

pthread_mutex_t m;

pthread_cond_t c;

...

pthread_mutex_lock(&m);

https://www.360docs.net/doc/578035450.html,_sec = time(NULL) + TIMEOUT;

https://www.360docs.net/doc/578035450.html,_nsec = 0;

while (cond == FALSE) {

err = pthread_cond_timedwait(&c, &m, &to);

if (err == ETIMEDOUT) {

/* timeout, do something */

break;

}

}

pthread_mutex_unlock(&m);

--------------------------------------------------------------------------------

pthread_cond_timedwait 返回值

pthread_cond_timedwait() 在成功完成之后会返回零。其他任何返回值都表示出现了错误。如果出现以下任一情况,该函数将失败并返回对应的值。

EINVAL

描述:

cv 或 abstime 指向的地址非法。

ETIMEDOUT

描述:

abstime 指定的时间已过。

超时会指定为当天时间,以便在不重新计算值的情况下高效地重新测试条件,如示例 4–9 中所示。

在指定的时间间隔内阻塞

pthread_cond_reltimedwait_np(3C) 的用法与 pthread_cond_timedwait() 的用法基本相同,唯一的区别在于 pthread_cond_reltimedwait_np() 会采用相对时间间隔而不是将来的绝对时间作为其最后一个参数的值。

pthread_cond_reltimedwait_np 语法

int pthread_cond_reltimedwait_np(pthread_cond_t *cv,

pthread_mutex_t *mp,

const struct timespec *reltime);#include

#include

pthread_cond_t cv;

pthread_mutex_t mp;

timestruct_t reltime;

int ret;

/* wait on condition variable */

ret = pthread_cond_reltimedwait_np(&cv, &mp, &reltime); pthread_cond_reltimedwait_np() 每次返回时调用线程都会锁定并且拥有互斥锁,即使pthread_cond_reltimedwait_np() 返回错误时也是如此。对于 Solaris 线程,请参见cond_reltimedwait(3C)。pthread_cond_reltimedwait_np() 函数会一直阻塞,直到该条件获得信号,或者最后一个参数指定的时间间隔已过为止。

-------------------------------------------------------------------------------- 注–

pthread_cond_reltimedwait_np() 也是取消点。

--------------------------------------------------------------------------------

pthread_cond_reltimedwait_np 返回值

pthread_cond_reltimedwait_np() 在成功完成之后会返回零。其他任何返回值都表示出现了错误。如果出现以下任一情况,该函数将失败并返回对应的值。

EINVAL

描述:

cv 或 reltime 指示的地址非法。

ETIMEDOUT

描述:

reltime 指定的时间间隔已过。

解除阻塞所有线程

对于基于 cv 所指向的条件变量阻塞的线程,使用 pthread_cond_broadcast(3C) 可以解除阻塞所有这些线程,这由 pthread_cond_wait() 来指定。

pthread_cond_broadcast 语法

int pthread_cond_broadcast(pthread_cond_t *cv);#include

pthread_cond_t cv;

int ret;

/* all condition variables are signaled */

ret = pthread_cond_broadcast(&cv); 如果没有任何线程基于该条件变量阻塞,则调用pthread_cond_broadcast() 不起作用。对于 Solaris 线程,请参见cond_broadcast 语法。

由于 pthread_cond_broadcast() 会导致所有基于该条件阻塞的线程再次争用互斥锁,因此请谨慎使用 pthread_cond_broadcast()。例如,通过使用 pthread_cond_broadcast(),线程可在资源释放后争用不同的资源量,如示例 4–10 中所示。

-------------------------------------------------------------------------------- 示例 4–10 条件变量广播

pthread_mutex_t rsrc_lock;

pthread_cond_t rsrc_add;

unsigned int resources;

get_resources(int amount)

{

pthread_mutex_lock(&rsrc_lock);

while (resources < amount) {

pthread_cond_wait(&rsrc_add, &rsrc_lock);

}

resources -= amount;

pthread_mutex_unlock(&rsrc_lock);

}

add_resources(int amount)

{

pthread_mutex_lock(&rsrc_lock);

resources += amount;

pthread_cond_broadcast(&rsrc_add);

pthread_mutex_unlock(&rsrc_lock);

}

--------------------------------------------------------------------------------

请注意,在add_resources() 中,首先更新resources 还是首先在互斥锁中调用pthread_cond_broadcast() 无关紧要。

应在互斥锁的保护下修改相关条件,该互斥锁用于获得信号的条件变量中。否则,可能在条件变量的测试和 pthread_cond_wait() 阻塞之间修改该变量,这会导致无限期等待。

pthread_cond_broadcast 返回值

pthread_cond_broadcast() 在成功完成之后会返回零。其他任何返回值都表示出现了错误。如果出现以下情况,该函数将失败并返回对应的值。

EINVAL

描述:

cv 指示的地址非法。

销毁条件变量状态

使用 pthread_cond_destroy(3C) 可以销毁与 cv 所指向的条件变量相关联的任何状态。对于 Solaris 线程,请参见cond_destroy 语法。

pthread_cond_destroy 语法

int pthread_cond_destroy(pthread_cond_t *cv);#include

pthread_cond_t cv;

int ret;

/* Condition variable is destroyed */

ret = pthread_cond_destroy(&cv); 请注意,没有释放用来存储条件变量的空间。

pthread_cond_destroy 返回值

pthread_cond_destroy() 在成功完成之后会返回零。其他任何返回值都表示出现了错误。如果出现以下情况,该函数将失败并返回对应的值。

EINVAL

描述:

cv 指定的值无效。

唤醒丢失问题

如果线程未持有与条件相关联的互斥锁,则调用pthread_cond_signal() 或pthread_cond_broadcast() 会产生唤醒丢失错误。

满足以下所有条件时,即会出现唤醒丢失问题:

一个线程调用 pthread_cond_signal() 或 pthread_cond_broadcast()

另一个线程已经测试了该条件,但是尚未调用 pthread_cond_wait()

没有正在等待的线程

信号不起作用,因此将会丢失

仅当修改所测试的条件但未持有与之相关联的互斥锁时,才会出现此问题。只要仅在持有关联的互斥锁同时修改所测试的条件,即可调用pthread_cond_signal() 和pthread_cond_broadcast(),而无论这些函数是否持有关联的互斥锁。

生成方和使用者问题

并发编程中收集了许多标准的众所周知的问题,生成方和使用者问题只是其中的一个问题。此问题涉及到一个大小限定的缓冲区和两类线程(生成方和使用者),生成方将项放入缓冲区中,然后使用者从缓冲区中取走项。

生成方必须在缓冲区中有可用空间之后才能向其中放置内容。使用者必须在生成方向缓冲区中写入之后才能从中提取内容。

条件变量表示一个等待某个条件获得信号的线程队列。

示例 4–11 中包含两个此类队列。一个队列 (less) 针对生成方,用于等待缓冲区中出现空位置。另一个队列 (more) 针对使用者,用于等待从缓冲槽位的空位置中提取其中包含的信息。该示例中还包含一个互斥锁,因为描述该缓冲区的数据结构一次只能由一个线程访问。

-------------------------------------------------------------------------------- 示例 4–11 生成方和使用者的条件变量问题

typedef struct {

char buf[BSIZE];

int occupied;

int nextin;

int nextout;

pthread_mutex_t mutex;

pthread_cond_t more;

pthread_cond_t less;

} buffer_t;

buffer_t buffer;

--------------------------------------------------------------------------------

如示例 4–12 中所示,生成方线程获取该互斥锁以保护 buffer 数据结构,然后,缓冲区确定是否有空间可用于存放所生成的项。如果没有可用空间,生成方线程会调用

pthread_cond_wait()。pthread_cond_wait() 会导致生成方线程连接正在等待 less 条件获得信号的线程队列。less 表示缓冲区中的可用空间。

与此同时,在调用 pthread_cond_wait() 的过程中,该线程会释放互斥锁的锁定。正在等待的生成方线程依赖于使用者线程在条件为真时发出信号,如示例 4–12 中所示。该条件获得信号时,将会唤醒等待 less 的第一个线程。但是,该线程必须再次锁定互斥锁,然后才能从 pthread_cond_wait() 返回。

获取互斥锁可确保该线程再次以独占方式访问缓冲区的数据结构。该线程随后必须检查缓冲区中是否确实存在可用空间。如果空间可用,该线程会向下一个可用的空位置中进行写入。

与此同时,使用者线程可能正在等待项出现在缓冲区中。这些线程正在等待条件变量 more。刚在缓冲区中存储内容的生成方线程会调用 pthread_cond_signal() 以唤醒下一个正在等待的使用者。如果没有正在等待的使用者,此调用将不起作用。

最后,生成方线程会解除锁定互斥锁,从而允许其他线程处理缓冲区的数据结构。

--------------------------------------------------------------------------------

示例 4–12 生成方和使用者问题:生成方

void producer(buffer_t *b, char item)

{

pthread_mutex_lock(&b->mutex);

while (b->occupied >= BSIZE)

pthread_cond_wait(&b->less, &b->mutex);

assert(b->occupied < BSIZE);

b->buf[b->nextin++] = item;

b->nextin %= BSIZE;

b->occupied++;

/* now: either b->occupied < BSIZE and b->nextin is the index

of the next empty slot in the buffer, or

b->occupied == BSIZE and b->nextin is the index of the

next (occupied) slot that will be emptied by a consumer

(such as b->nextin == b->nextout) */

pthread_cond_signal(&b->more);

pthread_mutex_unlock(&b->mutex);

}

--------------------------------------------------------------------------------

请注意 assert() 语句的用法。除非在编译代码时定义了 NDEBUG,否则 assert() 在其参数的计算结果为真(非零)时将不执行任何操作。如果参数的计算结果为假(零),则该程序会中止。在多线程程序中,此类断言特别有用。如果断言失败,assert() 会立即指出运行时问题。assert() 还有另一个作用,即提供有用的注释。

以 /* now: either b->occupied ... 开头的注释最好以断言形式表示,但是由于语句过于复杂,无法用布尔值表达式来表示,因此将用英语表示。

断言和注释都是不变量的示例。这些不变量是逻辑语句,在程序正常执行时不应将其声明为假,除非是线程正在修改不变量中提到的一些程序变量时的短暂修改过程中。当然,只要有线程执行语句,断言就应当为真。

使用不变量是一种极为有用的方法。即使没有在程序文本中声明不变量,在分析程序时也应将其视为不变量。

每次线程执行包含注释的代码时,生成方代码中表示为注释的不变量始终为真。如果将此注

释移到紧挨 mutex_unlock() 的后面,则注释不一定仍然为真。如果将此注释移到紧跟assert() 之后的位置,则注释仍然为真。

因此,不变量可用于表示一个始终为真的属性,除非一个生成方或一个使用者正在更改缓冲区的状态。线程在互斥锁的保护下处理缓冲区时,该线程可能会暂时声明不变量为假。但是,一旦线程结束对缓冲区的操作,不变量即会恢复为真。

示例 4–13 给出了使用者的代码。该逻辑流程与生成方的逻辑流程相对称。

--------------------------------------------------------------------------------

示例 4–13 生成方和使用者问题:使用者

char consumer(buffer_t *b)

{

char item;

pthread_mutex_lock(&b->mutex);

while(b->occupied <= 0)

pthread_cond_wait(&b->more, &b->mutex);

assert(b->occupied > 0);

item = b->buf[b->nextout++];

b->nextout %= BSIZE;

b->occupied--;

/* now: either b->occupied > 0 and b->nextout is the index

of the next occupied slot in the buffer, or

b->occupied == 0 and b->nextout is the index of the next (empty) slot that will be filled by a producer (such as b->nextout == b->nextin) */

pthread_cond_signal(&b->less);

pthread_mutex_unlock(&b->mutex);

return(item);

}

Java语言程序设计Java线程作业

选择题: 1、(3分)下列说法中错误的一项是() A、线程创建之后,可以从一个线程组转移到另一个线程组 B、新建的线程默认情况下属于其父线程所属的线程组 C、Java中的第一个线程都属于某个线程组 D、线程只能在其创建时设置所属的线程组 2、(3分)下列说法中错误的一项是() A、线程是一个程序的单个执行流 B、多线程是指一个程序的多个执行流 C、线程就是程序 D、多线程用于实现并发 3、(3分)下列说法中错误的一项是() A、java的线程体由Thread类的run()方法定义 B、java中每一个线程都有自己的名字 C、在程序中通过调用Thread类的run()方法创建线程对象 D、线程创建时已经确定了提供线程体的对象 4、(3分)在以下哪种情况下,线程进入就绪状态?() A、线程调用了notify()方法时 B、线程调用了sleep()方法时 C、线程调用了yield()方法时 D、线程调用了join()方法时 5、(3分)下列说法中错误的一项是() A、所有的对共享数据的访问都是临界区 B、临界区必须使用syschronized标识 C、共享数据的访问不一定全部使用synchronized加锁 D、共享数据的所有访问都必须使用synchronized加锁 6、(3分)下列有关线程的叙述中正确的一项是() A、使用start()方法可以使一个线程成为可运行的,但是它不一定立即开始运行 B、当一个线程因为抢占机制而停止运行时,它被放在可运行队列的前面 C、一旦一个线程被创建,它就立即开始运行

D、一个线程可能因为不同的原因而终止并进入终止状态 7、(3分)下列关于Thread类提供的线程控制方法的说法中,错误的一项是() A、在线程A中执行线程B的join()方法,则线程A等待直到B执行完成 B、currentThread()方法返回当前线程的引用 C、若线程A调用方法isAlive()返回值为true,则说明A正在执行中 D、线程A通过调用interrupt()方法来中断其阻塞状态 8、(3分)下列哪个方法可以使线程从运行状态进入其他阻塞状态() A、start B、wait C、sleep D、yield 9、(3分) 线程调用sleep()方法后,该线程将进入以下哪种状态?() A、死亡状态 B、阻塞状态 C、就绪状态 D、运行状态 10、(3分)Thread类位于下列那个包中?() A、java.io B、java.awt C、java.util D、https://www.360docs.net/doc/578035450.html,ng 11、(3分)下列说法中错误的一项是() A、新建的线程调用start()方法就能立即进入运行状态 B、线程操作的数据来自Runnable实例 C、线程从传递给Runnable实例run()方法开始执行

Java多线程实现

下面要和大家分享的是Java多线程的实践,其实Java增加了新的类库并发集java.util.concurrent,该类库为并发程序提供了丰富的API多线程编程在Java 5中更加容易,灵活。本文通过一个网络服务器模型,来实践Java5的多线程编程,该模型中使用了Java5中的线程池,阻塞队列,可重入锁等,还实践了Callable,Future 等接口,并使用了Java 的另外一个新特性泛型。 简介 本文将实现一个网络服务器模型,一旦有客户端连接到该服务器,则启动一个新线程为该连接服务,服务内容为往客户端输送一些字符信息。一个典型的网络服务器模型如下: 1. 建立监听端口。 2. 发现有新连接,接受连接,启动线程,执行服务线程。 3. 服务完毕,关闭线程。 这个模型在大部分情况下运行良好,但是需要频繁的处理用户请求而每次请求需要的服务又是简短的时候,系统会将大量的时间花费在线程的创建销毁。Java 5的线程池克服了这些缺点。通过对重用线程来执行多个任务,避免了频繁线程的创建与销毁开销,使得服务器的性能方面得到很大提高。因此,本文的网络服务器模型将如下: 1. 建立监听端口,创建线程池。 2. 发现有新连接,使用线程池来执行服务任务。 3. 服务完毕,释放线程到线程池。 下面详细介绍如何使用Java 5的concurrent包提供的API来实现该服务器。 初始化 初始化包括创建线程池以及初始化监听端口。创建线程池可以通过调用java.util.concurrent.Executors类里的静态方法newChahedThreadPool或是newFixedThreadPool来创建,也可以通过新建一个 java.util.concurrent.ThreadPoolExecutor实例来执行任务。这里我们采用newFixedThreadPool方法来建立线程池。 ExecutorService pool = Executors.newFixedThreadPool(10); 表示新建了一个线程池,线程池里面有10个线程为任务队列服务。 使用ServerSocket对象来初始化监听端口。

线程的创建与撤销

师范大学 操作系统(本科) 实验报告 院系:计算机科学技术学院班级: 学生姓名: 学号:20141602141041 指导教师: 教师评阅结果: 教师评语: 实验日期年月日

实验名称: 实验二:线程的创建与撤销 一、实验目的和要求: 熟悉windows系统提供线程的创建与撤销系统调用。 掌握windows系统环境下的线程的创建与撤销方法。 二、实验内容: 使用系统调用createthread()创建一个子线程,并在子线程中显示:thread is runing!,并使用sleep()使线程挂起5s之后使用exitthread(0)撤销线程。 三、实验技术和方法: 1.创建线程 2.撤销线程 3.终止线程 四、实验环境: 使用vc++ 6.0

五、实验步骤和结果:

实验代码: #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////// //////// // The one and only application object CWinApp theApp;

using namespace std; void ThreadName1(); static HANDLE hHandle1=NULL; DWORD dwThreadID1; int _tmain(int argc, TCHAR* argv[], TCHAR* envp[]) { int nRetCode = 0; hHandle1=CreateThread((LPSECURITY_ATTRIBUTES) NULL, 0, (LPTHREAD_START_ROUTINE) ThreadName1, (LPVOID) NULL, 0, &dwThreadID1); Sleep(5000); CloseHandle(hHandle1); ExitThread(0); return nRetCode; }

作业3-线程实现加减乘除

电子科技大学 作业报告 学生姓名:学号:指导教师: 学生E-mail: 一、作业名称 线程实现加减乘除服务 二、作业要求 试验要求: 使用多个队列,每一个计算线程有独立的队列用于存储计算请求,请求线程可用一个队列用于接收结果。 只需要实现A(+,-,X,/)B简单两元计算 请求线程与计算线程是多对多关系 三、设计与实现 3.1设计方案 根据试验要求,线程间的通信用队列,所以通信结构就不用考虑了,提到队列,我们就要做初始化队列,朝队列里面添加信息,从队列头部取走信息这些工作,但是在队列的操作中,最重要的就是线程的同步问题了,我选择了一个互斥锁和一个条件变量相结合的方法,互斥锁保证对队列的任何操作必须唯一,条件变量使我们可以放心的等待队列有内容,接着我们就需要选择我们的整体结构了。 最开始,我考虑用一个队列,发送线程把计算式结构体放到这个队列里面,这个计算式结构体里面包括接收线程的ID号,每个接收线程轮流去读取队列,但是只能读取接受进程是自己的结构体,然后再把这些结果都返回给主线程,主

线程对这个计算式进行打印到屏幕,但是这个模型有一定的限制,那就是接受计算线程个数每次去取得互斥锁,并准备去取计算式,发现这个结构体里面的接受线程不是自己,不得不释放互斥锁,轮流这样做,这样的效率会比较低。 由于计算类型是确定的,经过综合考虑,我觉得还是初始化四个发送队列,每个计算线程(加,减,乘,除)各对应一个队列,发送线程会根据自己产生的计算式类型,把这个结构体放入对应的队列中,这样接收线程在队列不空的情况下,就可以去取,并且保证可以取到,同时初始化四个回传队列,计算线程计算完毕后,把结果回传个产生这个计算式的线程。这样虽然会占有一定的空间,但是对于充足的内存,空间换时间的做法还是可以选择的。 在最后选择进程结束时,我考虑的是计算线程不能退出,因为暂时队列为空,不代表没有了该类型的计算式,但是还要保证最后整个线程正常退出,只能让所有的发送线程在接收到各自全部的计算式后返回主线程,这样主线程根据返回的发送线程的个数来判断是否结束整个进程。 另外发送线程的个数以及每个发送线程发送多少个计算式作业,都是用宏定义定义的,只要改变这两个值就可以修改线程的个数和现成的作业数,我这里主要的思想还是想把加减乘除与0,1,2,3对应起来,这样可以保证四个发送队列的类型与加减乘除匹配起来,并且计算线程id数组的下标刚好也用0,1,2,3与加减乘除对应,这样可以简单好理解。 结构图1

程序进程线程并发与异步

实验七程序进程与线程 7.1实验目的 重点理解程序进程与线程的联系与区别,程序运行中的同步与异步概念。掌握Windows平台中的进程对象,进程的属性与参数,编程实现进程启动及其输入输出重定向的实现,程序的同步与异步调用实现。 7.2程序进程与线程 在Windows平台运行程序时首先创建进程描述块(又叫进程控制块),进程控制块包含进程需要的各项资源,进程仅是资源分配的单位。用户编写的程序代码串行存储成磁盘文件,程序运行时系统依据主程序入口创建主线程,工作线程由主线程或其它线程创建,所有线程并发执行,文件中串行的代码经克隆后在机器中并行执行。程序进程与线程的关系由图7-1表示。 图7-1程序进程与线程 Windows平台CPU运行调度的最小单位是线程,所有可运行的线程排成队列,图7-2描绘CPU以时间片轮转的方式执行队列中的线程。

图7-2CPU轮转与线程的并发执行 7.3程序运行中的同步与异步概念 应用程序生成的线程与Windows平台的系统线程是并发执行的,当用户线程调用系统函数时系统线程执行任务并生成结果。用户线程对目标结果有两种依赖方式,要求目标结果必须出现的系统调用即是同步调用,仅有函数调用无须目标结果出现的系统调用即是异步调用。单独线程内的代码或函数是顺次执行前后代码间形成前趋制约,这种前趋制约存在于多个线程间就形成同步运行。多个并发运行的线程如果不存在前趋制约,线程推进速率不互相牵制即形成异步运行,图7-3描绘线程中的同步调用与异步调用。 图7-3系统函数的同步调用与异步调用 .NET框架类中很多的方法同时支持同步与异步方式,比如FileStream类提供对文件流操作,有同步读写操作,也支持异步读写操作。网络通信程序中Socket类即支持同步的Accept 方法,也支持异步方式的BeginAccept方法用于接受一个传入的连接,网络数据接收即具有同步的Receive方法又有异步的BeginReceive方法等。操作系统提供的多种服务调用以驱动线程或系统线程的形式与用户线程异步运行,同步调用与异步调用对用户界面线程影响较大,例如网页浏览器采用的同步方式果获取网页内容,会产生明显的停滞现象,支持异步方式的Ajax技术会更受用户的欢迎,浏览器在获取网页的内容时,部分区域内容的更新不影响其它区域的显

北大操作系统高级课程-陈向群作业-XV6进程线程

阅读代码: 1.基本头文件: types.h param.h memlayout.h defs.h x86.h asm.h mmu.h elf.h 2.进程线程部分: vm.c proc.h proc.c swtch.S kalloc.c 以及相关其他文件代码 强调一下:由于内存管理部分还没有学到,所以请同学们遇到相关的代码和问题时,先将问题记录下来,到学过之后,再结合进程线程管理部分进行深入学习,最后要求对XV6有整体的理解。 请大家围绕如下一些问题阐述原理课的相关内容,以及XV6中是如何实现的。 1.什么是进程,什么是线程?操作系统的资源分配单位和调度单位分别是什么?XV6中的 进程和线程分别是什么,都实现了吗? 答:进程是在多道程序系统出现以后,为了描述系统内部各作业的活动规律而引进的概念。进程有3个基本状态,运行状态、就绪状态和等待状态(或称阻塞状态);进程只能由父进程建立,系统中所有的进程形成一种进程树的层次体系;挂起命令可有进程自己和其他进程发出,但是解除挂起命令只能由其他进程发出。进程是具有独立功能的程序关于某个数据集合上的一次运行活动,是系统进行资源分配和调度的独立单位。 线程可称为轻量级的进程,是操作系统可以运行调度的最小单位。线程是进程内的一个相对独立的可执行的单元。若把进程称为任务的话,那么线程则是应用中的一个子任务的执行。 不论操作系统中是否引入了线程,操作系统中资源分配的基本单位都是进程。如果操作系统没有引入线程那么进程就是调度的基本单位。线程并不独立拥有资源,它仅仅分配了一些运行必备的资源。一个进程中的多个线程共同分享进程中的资源。在引入了线程的操作系统中,线程就变成了调度的基本单位,进程中的部分线程阻塞并不代表该线程被阻塞。 xv6操作系统实现了一个基于进程(没有实现线程)的简单进程管理机制。通过对proc.h 文件的阅读了解到xv6的进程中定义了一个context结构,一个枚举类型proc_state定义了UNUSED, EMBRYO, SLEEPING, RUNNABLE, RUNNING, ZOMBIE 这6种进程的状态,proc结构定义了进程控制块的内容,cpu结构定义了寄存器和栈指针。 2.进程管理的数据结构是什么?在Windows,Linux,XV6中分别叫什么名字?其中包含哪 些内容?操作系统是如何进行管理进程管理数据结构的?它们是如何初始化的? 答:进程管理的数据结构是进程控制块(PCB)。在Linux中进程控制块的结构是由一个叫task_struct的数据结构定义的,ask_struct存在/include/ linux/sched.h中,其中包括管理进程

多线程练习题目

多线程 一、单项 1.下述哪个选项为真?( ) A.Error类是一个RoutimeException异常 B.任何抛出一个RoutimeException异常的语句必须包含在try块之内 C.任何抛出一个Error对象的语句必须包含在try块之内 D. 任何抛出一个Exception异常的语句必须包含在try块之内 2.下列关于Java线程的说法哪些是正确的?( ) A.每一个Java线程可以看成由代码、一个真实的CPU以及数据3部分组成 B.创建线程的两种方法,从Thread类中继承的创建方式可以防止出现多父类问题 C.Thread类属于java.util程序包 D.以上说法无一正确 3.哪个关键字可以对对象加互斥锁?( ) A.transient B.synchronized C.serialize D.static 4.下列哪个方法可用于创建一个可运行的类?() A.public class X implements Runable { public void run() {……} } B. public class X implements Thread { public void run() {……} } C. public class X implements Thread { public int run() {……} } D.public class X implements Runable { protected void run() {……} } 5.下面哪个选项不会直接引起线程停止执行?( ) A.从一个同步语句块中退出来 B.调用一个对象的wait方法 C.调用一个输入流对象的read方法 D.调用一个线程对象的setPriority方法 6.使当前线程进入阻塞状态,直到被唤醒的方法是( ) A.resume()方法 B.wait()方法 C.suspend()方法 D.notify()方法 7.运行下列程序,会产生的结果是( ) public class X extends Thread implements Runnable { public void run(){ System.out.println(“this is run()”); } public static void main(String[] args) { Thread t=new Thread(new X()); t.start(); } }

java线程练习题及答案

线程与线程类 1 线程的概念 线程的概念来源于计算机的操作系统的进程的概念。进程是一个程序关于某个数据集的一次运行。也就是说,进程是运行中的程序,是程序的一次运行活动。 线程和进程的相似之处在于,线程和运行的程序都是单个顺序控制流。有些教材将线程称为轻量级进程(light weight process)。线程被看作是轻量级进程是因为它运行在一个程序的上下文内,并利用分配给程序的资源和环境。 作为单个顺序控制流,线程必须在运行的程序中得到自己运行的资源,如必须有自己的执行栈和程序计数器。线程内运行的代码只能在该上下文内。因此还有些教程将执行上下文(execution context)作为线程的同义词。 所有的程序员都熟悉顺序程序的编写,如我们编写的名称排序和求素数的程序就是顺序程序。顺序程序都有开始、执行序列和结束,在程序执行的任何时刻,只有一个执行点。线程(thread )则是进程中的一个单个的顺序控制流。单线程的概念很简单,如图1所示。 多线程(multi-thread )是指在单个的程序内可以同时运行多个不同的线程完成不同的任务,图2说明了一个程序中同时有两个线程运行。 图1 单线程程序示意图 图2 多线程程序示意图 有些程序中需要多个控制流并行执行。例如, for(int i = 0; i < 100; i++) System.out.println("Runner A = " + i); for(int j = 0; j < 100; j++ ) System.out.println("Runner B = "+j); 上面的代码段中,在只支持单线程的语言中,前一个循环不执行完不可能执行第二个循环。要使两个循环同时执行,需要编写多线程的程序。 很多应用程序是用多线程实现的,如Hot Java Web 浏览器就是多线程应用的例子。在Hot Java 浏览器中,你可以一边滚动屏幕,一边下载Applet 或图像,可以同时播放动画和声音等。 2 Thread 类和Runnable 接口 多线程是一个程序中可以有多段代码同时运行,那么这些代码写在哪里,如何创建线程对象呢? 首先,我们来看Java 语言实现多线程编程的类和接口。在https://www.360docs.net/doc/578035450.html,ng 包中定义了Runnable 接口和Thread 类。

实验二线程的创建

实验二创建线程 一、实验目的 1. 通过创建线程、观察正在运行的线程和终止线程的程序设计和调试操作,进一步熟悉操作系统的线程概念,理解进程与线程之间的关系。 2. 通过阅读和分析实验程序,学习创建线程、观察线程和终止线程的程序设计方法。 二、实验内容 1. 创建线程 创建线程并因而成就一个多线程程序,是以CreateThread()作为一切行动的开始.此函数的原型如下: HANDLE CreateThread{ LPSECURITY_ATTRIBUTES lpThreadAttributes, DWORD dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId}; 如果CreateThread()成功,返回一个新创建的线程的handle。 如果CreateThread()失败,返回一个NULL。可以调用GetLastError()获知原因。

2. 终止线程 线程结束代码可以依靠调用GetExitCodeThread()完成。 BOOL GetExitCodeThread{ HANDLE hThread, /*由CreateThread()传回的线程handle*/ LPDWORD lpExitCode /*指向一个DWORD,用于接受结束代码*/ }; 如果成功,GetExitCodeThread()传回TRUE,否则传回FALSE.如果线程已结束,那么线程的结束代码会被放在lpExitCode参数中带回来.如果线程尚未结束,lpExitCode带回来的值是STILL_ACTIVE。 如果需要用更强制性的手法结束一个线程,可以使用ExitThread()。 三、实验步骤 (1)开启五个线程,设计一个基于Win32多线程应用程序。 (2)基于Win32多线程应用程序,启动两个线程,当用户按下任意键时,试图退出。 (3)验证Thread 使用自己的 Stack 存放 function 中的 local variable。四.程序设计 (1)声明线程标准函数形式,创建等待对象的句柄hThrd,创建接收新线程ID的DWORD变量。进行for循环,执行线程内容ThreadFunc并返回每个核心对象hThrd。之后等待线程全部完成,结束程序。 (2)声明线程标准函数形式,创建等待对象的句柄hThrd1、hThrd2,创建获取线程退出代码的exitCode1、exitCode2,创建接收新线程ID的DWORD变量。执行线程内容ThreadFunc并返回每个核心对象hThrd并输出相关提示信息。进行for循环,接收用户按下的任意键信息,调用GetExitCodeThread等待一个线程的结束,使用GetExitCodeThread传回线程函数ThreadFunc的返回值。函数中用一个死循环,保证两个线程能够完整的运行完成,getch()函数接收用户输入,尝试打断线程,但后面代码保护了线程的继续执行,直至两个线程都执行完成,输出各自的返回值并退出。 (3)验证性程序。

OS中的进程线程同步机制

OS中的进程/线程同步机制 1 常用并发机制 1.1 信号量(Semaphore) 用于进程间传递信号的一个整数值,在信号上只可以进行三种操作,即初始化、递减和递增,这三种操作都是原子操作。递减操作用于阻塞一个进程,递增操作用于解除一个进程的阻塞。信号量也称为计数信号量或一般信号量 1.2 二元信号量(Binary Semaphore) 只取0值和1值的信号量。 1.3 互斥量(Mutex) 类似于二元信号量。关键在于为其加锁(设定值为0)的进程和为其解锁(设定值为1)的进程必须为同一个进程。 1.4 条件变量(Cond) 一种数据类型,用于阻塞进程或线程,直到特定的条件为真。 1.5 管程(Monitor) 一种编程语言结构,它在一个抽象数据类型中封装了变量、访问过程和初始化代码。管程的变量只能由管程自身的访问过程访问,每次只能有一个进程在其中执行,访问过程即临界区。管程可以有一个等待进程队列。 1.6 事件标志(Event Sign) 用作同步机制的一个内存字。应用程序代码可为标志中的每个位关联不同的事件。通过测试相关的一个或多个位,线程可以等待一个或多个事件。在全部所需位都被设定(AND)或至少一个位被设定(OR)之前,线程会一直被阻塞。 1.7 信箱/消息(Mailbox) 两个进程间交换信息的一种方法,也可用于同步。 1.8 自旋锁(Spin Lock) 一种互斥机制,进程在一个无条件循环中执行,等待锁变量的值可用。

2 常用进程/线程同步机制介绍 2.1 Windows OS中常用进程/线程同步机制 2.1.1 临界区(Critical Section) 可用于进程和线程同步。 保证在某一时刻只有一个线程能访问数据的简便办法。在任意时刻只允许一个线程对共享资源进行访问。如果有多个线程试图同时访问临界区,那么在有一个线程进入后其他所有试图访问此临界区的线程将被挂起,并一直持续到进入临界区的线程离开。临界区在被释放后,其他线程可以继续抢占,并以此达到用原子方式操作共享资源的目的。 临界区包含两个操作原语: EnterCriticalSection()进入临界区 LeaveCriticalSection()离开临界区 EnterCriticalSection()语句执行后代码将进入临界区以后无论发生什么,必须确保与之匹配的LeaveCriticalSection()都能够被执行到。否则临界区保护的共享资源将永远不会被释放。虽然临界区同步速度很快,但却只能用来同步本进程内的线程,而不可用来同步多个进程中的线程。 MFC提供了很多功能完备的类,我用MFC实现了临界区。MFC为临界区提供有一个CCriticalSection类,使用该类进行线程同步处理是非常简单的。只需在线程函数中用CCriticalSection类成员函数Lock()和UnLock()标定出被保护代码片段即可。Lock()后代码用到的资源自动被视为临界区内的资源被保护。UnLock后别的线程才能访问这些资源。 2.1.2 互斥量(Mutex) 进程和线程都可用的一种同步机制。互斥量跟临界区很相似,只有拥有互斥对象的线程才具有访问资源的权限,由于互斥对象只有一个,因此就决定了任何情况下此共享资源都不会同时被多个线程所访问。当前占据资源的线程在任务处理完后应将拥有的互斥对象交出,以便其他线程在获得后得以访问资源。互斥量比临界区复杂。因为使用互斥不仅仅能够在同一应用程序不同线程中实现资源的安全共享,而且可以在不同应用程序的线程之间实现对资源的安全共享。 互斥量包含的几个操作原语: CreateMutex()创建一个互斥量 OpenMutex()打开一个互斥量 ReleaseMutex()释放互斥量 WaitForMultipleObjects()等待互斥量对象 2.1.3 信号量(Semaphore) 进程和线程都可用的同步机制。 信号量对象对线程的同步方式与前面几种方法不同,信号允许多个线程同时使用共享资源,这与操作系统中的PV操作相同。它指出了同时访问共享资源的线程最大数目。它允许多个线程在同一时刻访问同一资源,但是需要限制在同一

Java第七单元练习题-Java多线程机制

7Java多线程机制 7.1单项选择题 1. 线程调用了sleep()方法后,该线程将进入()状态。 A. 可运行状态 B. 运行状态 C. 阻塞状态 D. 终止状态 2. 关于java线程,下面说法错误的是() A. 线程是以CPU为主体的行为 B. java利用线程使整个系统成为异步 C. 创建线程的方法有两种:实现Runnable接口和继承Thread类 D. 新线程一旦被创建,它将自动开始运行 3. 在java中的线程模型包含() A. 一个虚拟处理器 B. CPU执行的代码 C. 代码操作的数据 D. 以上都是 4.在java语言中,临界区可以是一个语句块,或者是一个方法,并用()关键字标识。 A. synchronized B. include C. import D. Thread 5. 线程控制方法中,yield()的作用是() A. 返回当前线程的引用 B. 使比其低的优先级线程执行 C. 强行终止线程 D. 只让给同优先级线程运行 6. 线程同步中,对象的锁在()情况下持有线程返回 A. 当synchronized()语句块执行完后 B. 当在synchronized()语句块执行中出现例外(exception)时 C. 当持有锁的线程调用该对象的wait()方法时 D. 以上都是 7. 在以下()情况下,线程就进入可运行状态 A. 线程调用了sleep()方法时 B. 线程调用了join()方法时

C. 线程调用了yield()方法时 D. 以上都是 8. java用()机制实现了进程之间的异步执行 A. 监视器 B. 虚拟机 C. 多个CPU D. 异步调用 类的方法中,toString()方法的作用是() A. 只返回线程的名称 B. 返回当前线程所属的线程组的名称 C. 返回当前线程对象 D. 返回线程的名称 语言具有许多优点和特点,下列选项中,哪个反映了Java程序并行机制的特点() A. 安全性 B. 多线程 C. 跨平台 D. 可移值 11.以下哪个关键字可以用来对对象加互斥锁?() A. transient B. synchronized C. serialize D. static 12.下面关于进程、线程的说法不正确的是( )。 A.进程是程序的一次动态执行过程。一个进程在其执行过程中,可以产生多个线程——多线程,形成多条执行线索。 B.线程是比进程更小的执行单位,是在一个进程中独立的控制流,即程序内部的控制流。线程本身不能自动运行,栖身于某个进程之中,由进程启动执行。 C.Java多线程的运行与平台无关。 D.对于单处理器系统,多个线程分时间片获取CPU或其他系统资源来运行。对于多处理器系统,线程可以分配到多个处理器中,从而真正的并发执行多任务。 7.2填空题 1.________是java程序的并发机制,它能同步共享数据、处理不同的事件。 2.线程是程序中的一个执行流,一个执行流是由CPU运行程序的代码、__________所形 成的,因此,线程被认为是以CPU为主体的行为。 3.线程的终止一般可以通过两种方法实现:自然撤销或者是__________. 4.线程模型在java中是由__________类进行定义和描述的。 5.线程的创建有两种方法:实现_________接口和继承Thread类。 6.多线程程序设计的含义是可以将程序任务分成几个________的子任务。 7.按照线程的模型,一个具体的线程也是由虚拟的CPU、代码与数据组成,其中代码与数 据构成了___________,线程的行为由它决定。 8.ava中,新建的线程调用start()方法、如(),将使线程的状态从New(新建状态)转换为 _________。 9.多线程是java程序的________机制,它能同步共享数据,处理不同事件。 10.进程是由代码、数据、内核状态和一组寄存器组成,而线程是表示程序运行状态的

C++多线程编程入门及范例详解

多线程编程之一——问题提出 一、问题的提出 编写一个耗时的单线程程序: 新建一个基于对话框的应用程序SingleThread,在主对话框IDD_SINGLETHREAD_DIALOG 添加一个按钮,ID为IDC_SLEEP_SIX_SECOND,标题为“延时6秒”,添加按钮的响应函数,代码如下: 1.void CSingleThreadDlg::OnSleepSixSecond() 2.{ 3.Sleep(6000);//延时6秒 4.} 编译并运行应用程序,单击“延时6秒”按钮,你就会发现在这6秒期间程序就象“死机”一样,不在响应其它消息。为了更好地处理这种耗时的操作,我们有必要学习——多线程编程。 二、多线程概述 进程和线程都是操作系统的概念。进程是应用程序的执行实例,每个进程是由私有的虚拟地址空间、代码、数据和其它各种系统资源组成,进程在运行过程中创建的资源随着进程的终止而被销毁,所使用的系统资源在进程终止时被释放或关闭。 线程是进程内部的一个执行单元。系统创建好进程后,实际上就启动执行了该进程的主执行线程,主执行线程以函数地址形式,比如说main或WinMain函数,将程序的启动点提供给Windows 系统。主执行线程终止了,进程也就随之终止。 每一个进程至少有一个主执行线程,它无需由用户去主动创建,是由系统自动创建的。用户根据需要在应用程序中创建其它线程,多个线程并发地运行于同一个进程中。一个进程中的所有线程都在该进程的虚拟地址空间中,共同使用这些虚拟地址空间、全局变量和系统资源,所以线程间的通讯非常方便,多线程技术的应用也较为广泛。 多线程可以实现并行处理,避免了某项任务长时间占用CPU时间。要说明的一点是,目前大多数的计算机都是单处理器(CPU)的,为了运行所有这些线程,操作系统为每个独立线程安排一些CPU时间,操作系统以轮换方式向线程提供时间片,这就给人一种假象,好象这些线程都在同时运行。由此可见,如果两个非常活跃的线程为了抢夺对CPU的控制权,在线程切换时会消耗很多的CPU资源,反而会降低系统的性能。这一点在多线程编程时应该注意。 Win32SDK函数支持进行多线程的程序设计,并提供了操作系统原理中的各种同步、互斥和临界区等操作。Visual C++6.0中,使用MFC类库也实现了多线程的程序设计,使得多线程编程更加方便。 三、Win32API对多线程编程的支持 Win32提供了一系列的API函数来完成线程的创建、挂起、恢复、终结以及通信等工作。下面将选取其中的一些重要函数进行说明。

作业一

《嵌入式系统原理》作业一 注意: ●上交时间:下周上小课之前; ●不许打印答案,可以不抄题目,把答写在作业纸上就可以了; 一、填空题 1、ARM 机-机器),CM4处理器内部正在执行的指令的地址为0x08000100,此时读取 PC 2、CM4 4、根据操作数的来源不同,CM4处理器有不同的寻址方式,最快的寻址方式是 add r0,r1,r2 5、ATPCS中规定子程序间传递参数,参数个数少于等于4个时,使用寄存器 4 6、在CM4处理器中,寄存器和内存单元 7、伪操作import 伪操作“ldr r0,=label” 8、假设某嵌入式处理器有5级流水线,每级流水线所耗时间均为为0.2ms,则顺序执行30条指令需要耗费时间是 6.8 ms。 二、编程题 1、编写一段c语言和汇编语言的混合程序,在c语言函数中实现字符串拷贝(不许用字符串操作相关函数),函数原型如下:

void strcpy(char *src, char *dest) //即src所指向的字符串复制到dest中{ // 自己编写字符串拷贝代码 While(*src!=0) { *dest++=*src++ } } 然后,在汇编语言程序通过调用strcpy完成字符串src到dest的复制! PRESERVE8 THUMB AREA RESET, DATA, READONLY EXPORT __Vectors __Vectors DCD 0x20004000 ; Top of Stack DCD Reset_Handler ; Reset Handler AREA |.text|, CODE, READONLY Reset_Handler PROC EXPORT Reset_Handler [WEAK] ……;此处需将汇编代码补充完整 ldr r0,=src ldr r1,=0x20001000 Import strcpy Bl strcpy src dcb “Where is a will,where is a way!”,0 dest space 50 end

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

四种进程或线程同步互斥的控制方法 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 )

最新java多线程试题-答案

多线程 一.选择题 1.下列说法中错误的一项是(A) A.线程就是程序 B.线程是一个程序的单个执行流 B.多线程是指一个程序的多个执行流D.多线程用于实现并发 2.下列哪个一个操作不能使线程从等待阻塞状态进入对象阻塞状态(D) A.等待阴塞状态下的线程被notify()唤 B.等待阻塞状态下的纯种被interrput()中断 C.等待时间到 D.等待阻塞状态下的线程调用wait()方法 3.下列哪个方法可以使线程从运行状态进入其他阻塞状态(A) A.sleep B.wait C.yield D.start 4.下列说法中错误的一项是(D) A.一个线程是一个Thread类的实例 B.线程从传递给纯种的Runnable实例run()方法开始执行 C.线程操作的数据来自Runnable实例 D.新建的线程调用start()方法就能立即进入运行状态 5.下列关于Thread类提供的线程控制方法的说法中,错误的一项是(D) A.在线程A中执行线程B的join()方法,则线程A等待直到B执行完成 B.线程A通过调用interrupt()方法来中断其阻塞状态 C.若线程A调用方法isAlive()返回值为true,则说明A正在执行中 D.currentThread()方法返回当前线程的引用 6.下列说法中,错误的一项是() A.对象锁在synchronized()语句执行完之后由持有它的线程返还 B.对象锁在synchronized()语句中出现异常时由持有它的线程返还 C.当持有锁的线程调用了该对象的wait()方法时,线程将释放其持有的锁 D.当持有锁的线程调用了该对象的构造方法时,线程将释放其持有的锁 7.下面的哪一个关键字通常用来对对象的加锁,从而使得对对象的访问是排他的 A A.sirialize B transient C synchronized D static 二.填空题 1. 在操作系统中,被称做轻型的进程是线程 2. 多线程程序设计的含义是可以将一个程序任务分成几个并行的任务 3. 在Java程序中,run()方法的实现有两种方式:实现Runnable接口和继承Thread类 4 .多个线程并发执行时,各个线程中语句的执行顺序是确定的,但是线程之间的相对执行顺序是不确定的 6.Java中的对象锁是一种独占的排他锁 7.程序中可能出现一种情况:多个线种互相等待对方持有的锁,而在得到对方的锁之前都不会释放自己的锁,这就是死锁 8.线程的优先级是在Thread类的常数MIN_PRIORITY 和MAX_PRIORITY 之间的一个值 9.处于新建状态的线程可以使用的控制方法是start() 和stop() 。 10.一个进程可以包含多个线程

操作系统作业(研究生入学试题100)

操作系统作业 第一章 1.采用多道程序设计的系统中,系统的程序道数越多,系统的效率就越高吗?为什么? 2.在较低的multiprogramming level ,throughput 随着multiprogramming level的增加而增加.这种现象的最好的解释是:随着multiprogramming level的增加( ) A.系统开销增加了 B.一些系统资源逐步被完全利用了 C.每个请求的I/O量是固定的 D.每个请求在系统中运行的平均时间增加了 E.在系统资源中的潜在的并发活动量增加了 3.出现最高点后, throughput会随着multiprogramming level的增加而下降.这种现象最好的解释是:随着multiprogramming level的增加( ) A.每个请求的I/O量是固定的 B.一些系统资源逐步被完全利用 C.内存利用率改善了 D.每个请求在系统中运行的平均时间增加了 E.在系统资源中的潜在的并发活动量增加了 4.在下列给出的操作系统中,交互性最强的是( ) A.批量处理系统 B.实时系统 C.分时系统 D.网络操作系统 5.( )不是设计实时操作系统主要的追求目标 A.安全可靠 B.资源利用率 C.及时响应 D.快速处理 6.操作系统中,并发是指若干个事件( )发生 A.在同一时刻 B.一定在不同时刻 C.某一时间间隔内 D.依次在不同时间间隔内 7.下列作业类型中,适合在分时系统中运行的有( ),适合在批处理系统中运行的有( ) A.学习编程 B.数据统计 C.发送电子邮件 D.整理硬盘 8.操作系统的共同的特征( ) 9.操作系统功能实现,必须的硬件支持有( ) A.高速缓存 B.地址转换机构 C.多个处理器 D.光盘和磁带 E.中断装置 F.大容量快速磁盘 10.操作系统内核的功能有哪些? 11.多道程序技术提高了CPU的使用效率,这是因为发挥了( )和( )之间的并行工作能力. 12.( )系统具有同时管理和运行多个应用程序的能力 A.GUI B.Windows Applications C.Multitasking https://www.360docs.net/doc/578035450.html,working 13.目前,( )是没有版权的操作系统 A.LINUX B.UNIX C.WINDOWS D.MINIX [知识拓展] 17.下列指令中,哪些是特权指令? A.时钟设置 B.读时钟 C.由用户态转向管态 D.关中断

相关文档
最新文档