请问这种微博大麦网赠票请勿出售怎么使用

3578人阅读
C/C++语言基础(61)
简要例子:
#include &fstream&
ofstream out(&abc.txt&);
out && 3 && '\t' && &abc& &&
out.close( );
实际上就是把输出到屏幕上的cout,输出到了文件中fout。
#include &iostream&
#include &iomanip&
#include &fstream&
int main(){
char buffer[256];
ifstream myfile (&c:\\a.txt&);
ofstream outfile(&c:\\b.txt&);
if(!myfile){
cout && &Unable to open myfile&;
exit(1); // terminate with error
if(!outfile){
cout && &Unable to open otfile&;
exit(1); // terminate with error
int i=0,j=0;
int data[6][2];
while (! myfile.eof() )
myfile.getline (buffer,10);
sscanf(buffer,&%d %d&,&a,&b);
cout&&a&&& &&&b&&
data[i][0]=a;
data[i][1]=b;
myfile.close();
for(int k=0;k&i;k++){
outfile&&data[k][0] &&& &&&data[k][1]&&
cout&&data[k][0] &&& &&&data[k][1]&&
outfile.close();
无论读写都要包含&fstream&头文件
读:从外部文件中将数据读到程序中来处理
对于程序来说,是从外部读入数据,因此定义输入流,即定义输入流对象:ifsteam infile,infile就是输入流对象。
这个对象当中存放即将从文件读入的数据流。假设有名字为myfile.txt的文件,存有两行数字数据,具体方法:
infile.open(&myfile.txt&);&&&&& //注意文件的路径
infile&&a&&b;&&&&&&&&&&&&&&&&&& //两行数据可以连续读出到变量里
infile.close()
//如果是个很大的多行存储的文本型文件可以这么读:
char buf[1024];
//临时保存读取出来的文件内容
infile.open(&myfile.js&);
if(infile.is_open())
//文件打开成功,说明曾经写入过东西
while(infile.good() && !infile.eof())
memset(buf,0,1024);
infile.getline(buf,1204);
//这里可能对message做一些操作
cout&&message&&
infile.close();
写:将程序中处理后的数据写到文件当中
对程序来说是将数据写出去,即数据离开程序,因此定义输出流对象ofstream outfile,outfile就是输出流对象,这个对象用来存放将要写到文件当中的数据。具体做法:
outfile.open(&myfile.bat&);
//myfile.bat是存放数据的文件名
if(outfile.is_open())
outfile&&message&&
//message是程序中处理的数据
outfile.close();
cout&&&不能打开文件!&&&
/*/从键盘读入一行字符,把其中的字母依次放在磁盘文件fa2.dat中,再把它从磁盘文件读入程序,
将其中的小写字母改成大写字母,再存入磁盘fa3.dat中*/
#i nclude&fstream&
#i nclude&iostream&
#i nclude&cmath&
//////////////从键盘上读取字符的函数
void read_save(){
char c[80];
ofstream outfile(&f1.dat&);//以输出方工打开文件
if(!outfile){
cerr&&&open error!&&&//注意是用的是cerr
cin.getline(c,80);//从键盘读入一行字符
for(int i=0;c[i]!=0;i++) //对字符一个一个的处理,直到遇到'/0'为止
if(c[i]&=65&&c[i]&=90||c[i]&=97&&c[i]&=122){//保证输入的字符是字符
outfile.put(c[i]);//将字母字符存入磁盘文件
cout&&c[i]&&&&;
outfile.close();
void creat_data(){
ifstream infile(&f1.dat&,ios::in);//以输入的方式打开文件
if(!infile){
cerr&&&open error!&&&
ofstream outfile(&f3.dat&);//定义输出流f3.dat文件
if(!outfile){
cerr&&&open error!&&&
while(infile.get(ch)){//当读取字符成功时
if(ch&=122&&ch&=97)
outfile.put(ch);
infile.close();
outfile.close();
int main(){
read_save();
creat_data();
system(&pause&);
实例详解一:
实例详解二:
实例讲解三:
实例讲解四:
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:303803次
积分:5075
积分:5075
排名:第5048名
原创:172篇
转载:220篇
评论:12条
文章:21篇
阅读:15876
(1)(18)(2)(5)(16)(21)(6)(6)(1)(1)(6)(6)(9)(12)(49)(29)(51)(12)(9)(4)(1)(4)(8)(5)(2)(3)(2)(45)(25)(14)(3)(1)(2)(1)(1)(2)(1)(11)两个线程分别读写一个buffer,有没有办法不阻塞写buffer的那个线程
>>编程语言
>>>>文章内容
两个线程分别读写一个buffer,有没有办法不阻塞写buffer的那个线程
所属分类:VC/MFC  进程/线程/DLL----------------------------------------------------------------------其中写buffer的线程实时性要求很高,所以任何时候都不希望阻塞这个线程,读buffer的线程没有这样的限制。
想了半天,实在没想到好办法
----------------------------------------------------------------------读的时候如果有写copy出来一份,读线程从copy的buffer里面取数据,读完后删除临时buffer.
思路是参考Linux2.6内核的RCU机制.
--------------------------------------------------------laolaoliu2002:
你是说由写线程来copy一份出来?
不过我现在的情况是还有限制:可能多次读取以前读过的buffer。
所以也就是需要完全拷贝整个buffer,而不是读完就删除,这样比较费内存。
--------------------------------------------------------更新过后buffer里面已经不是原来的数据了.你是怎么读取以前读过的buffer的呢?如果能读出来那就不是更新而是重建了新的buffer.
--------------------------------------------------------楼主功能设计有些问题.&如laoliu所述.
--------------------------------------------------------如果不同步,其结果可想而知。
--------------------------------------------------------读的时间可能会比较长?
可以还是用一个临界区保护,设置一个写请求标志,在读的过程中(可能会有循环)随时判断这个写请求标志,如果发现为true了,读就立即取消,退出临界区。&&------临时想的,没有经过验证
--------------------------------------------------------这个就不能算buffer了,以前写的都得要保留。。
--------------------------------------------------------更新过后buffer里面已经不是原来的数据了.你是怎么读取以前读过的buffer的呢?如果能读出来那就不是更新而是重建了新的buffer.
------------------------------------------------
这个是一个比较大的buffer,比如64M(buffer的范围是256K到128M,用户可配置),写数据是顺序写入,可能写满了,可以再从头覆盖写入
而读数据可能读取buffer里任何一部分有效的数据
--------------------------------------------------------读的时间可能会比较长?
可以还是用一个临界区保护,设置一个写请求标志,在读的过程中(可能会有循环)随时判断这个写请求标志,如果发现为true了,读就立即取消,退出临界区。&------临时想的,没有经过验证
-----------------------------------------------------
读的时间不是很长
不过你的方法应该不能避免临界区冲突,毕竟线程随时都可能被切换
--------------------------------------------------------具体点的需求就是这样的:
线程A从网络上抓包并写入buffer,线程B是UI线程,用户需要随时看到网络数据包的内容,所以需要从buffer读取数据。
因为抓包线程实时性很强,所以不能阻塞(事实证明阻塞并且流量很大时肯定丢包)
--------------------------------------------------------开两个buffer,一个写,一个读,当读完以后就切换两个buffer。这样只需要在切换过程做同步,几乎没有阻塞。
--------------------------------------------------------To&楼上,如果用两个buffer,好像不用这么麻烦:
其中一个buffer(B1)只由写线程操作,另一个buffer(B2)由两个线程同时操作。
如果写线程发现读线程正在读B2,则不对其进行操作(这里没有阻塞写线程)
如果读线程发现写线程正在写B2,则阻塞该线程
现在是不想用两个buffer,如果用户配置的内存太大,则很浪费memory
--------------------------------------------------------写线程优先级设高一点?
--------------------------------------------------------buffer没必要很大,1M足矣。
--------------------------------------------------------可以考虑开辟一个虚拟内存共享池,&这样不浪费&physic&memory
--------------------------------------------------------写不进(得不到控制权)就丢了嘛,放弃这次操作,立即返回!
--------------------------------------------------------to&楼上:
那就是丢数据了,最不愿意看到的情况
--------------------------------------------------------按你的要求,可不可以不考虑同步问题?
因为,写数据是实时的,所以有数据就写进去.
而读数据,只是观察用的,就算有些数据稍微过期,也应该影响不大吧.
--------------------------------------------------------用InterlockExchangePtr原子化写线程的操作
--------------------------------------------------------楼上提的&原子化写线程&似乎是可行的.
--------------------------------------------------------设置读写位置标记,&如下:
char&buf[1024];
int&&nReadPos&&=&0;
int&&nWritePos&=&0;
写的时候从buf+nWritePos&处写入,写完成后要更新nWritePos的位置,
读的时候从buf+nReadPos&&处读取,读完成后要更新nReadPos的位置,保证nReadPos小于nWritePos就行了。
参考自ACE的ACE_Message_Block
--------------------------------------------------------给buffer创建一份拷贝,读线程只能读副本当中的内容!
写线程写完以后重新覆盖拷贝!
--------------------------------------------------------按你的要求,可不可以不考虑同步问题?
因为,写数据是实时的,所以有数据就写进去.
而读数据,只是观察用的,就算有些数据稍微过期,也应该影响不大吧.
-----------------------------------------------------
不是担心过期问题,而是读出来的数据就是错误的。比如说我正在读取的数据被写数据覆盖了
那么读取出来的就是不完整的数据
--------------------------------------------------------把对Buffer的读写放在临界区里吧。临界区是线程同步中耗资源比较少的一种同步方式,用这种方式同步时,操作系统不用进行内核/用户切换。
如果每次都创建copy的话,如果你的buffer比较大,恐怕效率还不及临界区高。
--------------------------------------------------------楼上的,临界区也会阻塞线程吧,这个任务的第一前提就是不阻塞线程!
--------------------------------------------------------用InterlockExchangePtr原子化写线程的操作
----------------------------------------------
这些原子操作好像只能操作一个变量,或者一个指针,读写操作都不可能对一个变量读写就完成的。
不知道是不是我理解有误
--------------------------------------------------------写之前暂停读线程,写完后在读不就好了
--------------------------------------------------------你认为一个指针就是一个变量这么简单么?
--------------------------------------------------------或许Exceptional&C++里讨论的swap函数对你会有帮助
--------------------------------------------------------谢谢各位。
最终的解决方案是采用比较浪费memory的方法,将整个memory分为N个固定长度(长度为网络的MTU,并且在每个块的末尾添加一个指针,如果收到超过MTU的Packet则动态分配一块buffer来存放超过MTU的部分放)的块。另外,还在每个块的尾部设置一个flag,在写之前设置为1,写完成之后设置为2。
读线程读取之前判断是否为1,如果是则表示正在写这个块,不再读取这个块。否则设置该flag为3,读取完成之后,再次判断该标志,如果还是3,则表示读取成功,否则表示读取过程中被写线程覆盖过,读取失败。
注:对每个块flag的操作均采用&InterLock&的原子操作。
这个方案唯一的缺点是比较浪费内存,如果收到的都是较小的Packet的话内存浪费率很高。&&&&&&&&在现代的程序开发中,资源的同步是一个比较重要的课题,在.Net中,对这部分有很丰富类库供我们使用,现在总结一下在各种情况下对资源同步的
&&&&&1.将字段声明为volatile
&&&&&&&&当一个字段被声明为volatile时,CLR中一些管理代码和内存的内部机制将负责对字段进行同步,并且总能保证读取到的字段信息都为最新的值,被声明为
volatile的字段必须具备以下特征之一
&&&&&&&&1.为引用类型
&&&&&&& 2.一个指针(在不安全代码中)
&&&&&&& 3.sbyte,byte,short,ushort,int,uint,char,float,bool
&&&&&&&&4.一个使用底层类型的枚举类型
&&&&&2.使用System.Threading.Interlocked 类
&&&&&&&&&在许多增对整数的操作中,我们都比较容易忽视线程的问题,例如执行下列代码
&&&&&&&& i = i + 1;
&&&&&&&& 实际上,上述代码分为3步骤
&&&&&&&&&&&&& 1).& 从内存中,读取i的值
&&&&&&&&&&&&& 2).& 将读取出来的值加1
&&&&&&&&&&&&& 3).& 将新的值写入内存中
&&&&&&&&&在单线程上,这个操作不会有任何问题,但是当i被多个线程访问时,问题就出现了,对i进行修改的线程,在上述的任何一部都有可能被其它读取线程打断,想象一下,
当操作线程执行完第二步,准备将新的值写入内存中时,此时其它读取线程获得了执行权,这时读取到的i的值并不是我们想要的,因此,这个操作不具备原子性,在.Net中,使用Interlocked类能确保操作的原子性,Interlocked类有以下的方法
&&&&&&&&& Increment
&&&&&&&&&&Decrement
&&&&&&&&& Exchange
&&&&&&&&&上述的方法的参数都为带ref 标识的参数,因此我们说,这些方法保证了数据的原子性,在多线程中,涉及到整数的操作时,数据的原子性值得考虑,Interlocked的操作代码如下
&&&&&&&&&&&&int&i&=&<span style="color: #;
&&&&&&&&&&&&System.Threading.Interlocked.Increment(ref&i);
&&&&&&&&&&&&Console.WriteLine(i);
&&&&&&&&&&&&System.Threading.Interlocked.Decrement(ref&i);
&&&&&&&&&&&&Console.WriteLine(i);
&&&&&&&&&&&&System.Threading.Interlocked.Exchange(ref&i,&<span style="color: #0);
&&&&&&&&&&&&Console.WriteLine(i);
&&&&&&&&& 输出信息如下
&&&&&&&&&&
&&&&&&&3.使用lock关键字
&&&&&&&&&&&&
&&&&&&&&&&地球人都知道,使用lock关键字可以获取一个对象的独占权,任何需要获取这个对象的操作的线程必须等待以获取该对象的线程释放独占权,lock提供了简单的同步资源的方法,与Java中的synchronized关键字类似。
&&&&&&&&& lock关键字的使用示例代码如下
object&o&=&new&object();
&&&&&&&&&&&&lock&(o)
&&&&&&&&&&&&{
&&&&&&&&&&&&&&&&Console.WriteLine("O");
&&&&&&&&&&&&}
&&&&&& 4.使用System.Theading.Monitor类进行同步
&&&&&&&&& System.Threading.Monitor类提供了与lock类似的功能,不过与lock不同的是,它能更好的控制同步块,当调用了Monitor的Enter(Object o)方法时,会获取o的独占权,直到调用Exit(Object o)方法时,才会释放对o的独占权,可以多次调用Enter(Object o)方法,只需要调用同样次数的Exit(Object o)方法即可,Monitor类同时提供了TryEnter(Object o,[int])的一个重载方法,该方法尝试获取o对象的独占权,当获取独占权失败时,将返回false,查看如下代码
&&&&&&&&&&
using&System.Collections.G
using&System.T
using&System.T
namespace&MonitorApplication
&&&&class&Program
&&&&&&&&private&static&object&m_monitorObject&=&new&object();
&&&&&&&&static&void&Main(string[]&args)
&&&&&&&&&&&&Thread&thread&=&new&Thread(Do);
&&&&&&&&&&&&thread.Name&=&"Thread1";
&&&&&&&&&&&&Thread&thread2&=&new&Thread(Do);
&&&&&&&&&&&&thread2.Name&=&"Thread2";
&&&&&&&&&&&&thread.Start();
&&&&&&&&&&&&thread2.Start();
&&&&&&&&&&&&thread.Join();
&&&&&&&&&&&&thread2.Join();
&&&&&&&&static&void&Do()
&&&&&&&&&&&&if&(!Monitor.TryEnter(m_monitorObject))
&&&&&&&&&&&&{
&&&&&&&&&&&&&&&&Console.WriteLine("Can't&visit&Object&"&+&Thread.CurrentThread.Name);
&&&&&&&&&&&&&&&&return;
&&&&&&&&&&&&}
&&&&&&&&&&&&try
&&&&&&&&&&&&{
&&&&&&&&&&&&&&&&Monitor.Enter(m_monitorObject);
&&&&&&&&&&&&&&&&Console.WriteLine("Enter&Monitor&"&+&Thread.CurrentThread.Name);
&&&&&&&&&&&&&&&&Thread.Sleep(<span style="color: #00);
&&&&&&&&&&&&}
&&&&&&&&&&&&finally
&&&&&&&&&&&&{
&&&&&&&&&&&&&&&&Monitor.Exit(m_monitorObject);
&&&&&&&&&&&&}
&当线程1获取了m_monitorObject对象独占权时,线程2尝试调用TryEnter(m_monitorObject),此时会由于无法获取独占权而返回false,输出信息如下
可以看到线程2无法获取到m_monitorObject的独占权,因此输出了一条错误信息.
Monitor类比lock类提供了一种更优秀的功能,考虑一下如下的场景
&&&&& 1.当你进入某家餐馆时,发现餐馆里坐满了客人,但是你又不想换地方,因此,你选择等待。
&&&&& 2.当餐馆内的服务员发现有空位置时,他通知前台的服务生,服务生给你安排了一个座位,于是你开始享受国际化的大餐。
使用Monitor类就可以实现如上的应用需求,在Monitor类中,提供了如下三个静态方法
&&&&&&&Monitor.Pulse(Object o)
&&&&&& Monitor.PulseAll(Object o)
&&&&&& Monitor.Wait(Object o ) // 重载函数
当调用Wait方法时,线程释放资源的独占锁,并且阻塞在wait方法直到另外的线程获取资源的独占锁后,更新资源信息并调用Pulse方法后返回。
我们模拟上述代码如下
using&System.Collections.G
using&System.T
using&System.T
namespace&MonitorApplication
&&&&class&Program
&&&&&&&&private&static&&object&m_isFull&=&new&object();
&&&&&&&&static&void&Main(string[]&args)
&&&&&&&&&&&&Thread&thread&=&new&Thread(HaveLunch);
&&&&&&&&&&&&thread.Name&=&"HaveLunchThread";
&&&&&&&&&&&&Thread&thread2&=&new&Thread(SeatChange);
&&&&&&&&&&&&thread2.Name&=&"SeatChangeThread";
&&&&&&&&&&&&thread.Start();
&&&&&&&&&&&&System.Threading.Thread.Sleep(<span style="color: #00);
&&&&&&&&&&&&thread2.Start();
&&&&&&&&&&&&thread.Join();
&&&&&&&&&&&&thread2.Join();
&&&&&&&&private&static&void&HaveLunch()
&&&&&&&&&&&&lock&(m_isFull)
&&&&&&&&&&&&{
&&&&&&&&&&&&&&&&Console.WriteLine("Wati&for&seta");
&&&&&&&&&&&&&&&&Monitor.Wait(m_isFull);
&&&&&&&&&&&&&&&&Console.WriteLine("Have&a&good&lunch!");
&&&&&&&&&&&&}
&&&&&&&&private&static&void&SeatChange()
&&&&&&&&&&&&lock&(m_isFull)
&&&&&&&&&&&&{
&&&&&&&&&&&&&&&&Console.WriteLine("Seat&was&changed");
&&&&&&&&&&&&&&&&Monitor.Pulse(m_isFull);
&&&&&&&&&&&&}
输出信息如下
可见,使用Monitor,我们能实现一种唤醒式的机制,相信在实际应用中有不少类似的场景。
&&&&&&&&& 5.使用System.Threading.Mutex(互斥体)类实现同步
&&&&&&&&& 在使用上,Mutex与上述的Monitor比较接近,不过Mutex不具备Wait,Pulse,PulseAll的功能,因此,我们不能使用Mutex实现类似的唤醒的功能,不过Mutex有一个比较大的特点,Mutex是跨进程的,因此我们可以在同一台机器甚至远程的机器上的多个进程上使用同一个互斥体。
&&&&&&&&&& 考虑如下的代码,代码通过获取一个称为ConfigFileMutex的互斥体,修改配置文件信息,写入一条数据,我们同时开启两个相同的进程进行测试
using&System.Collections.G
using&System.T
using&System.T
using&System.IO;
using&System.D
namespace&MonitorApplication
&&&&class&Program
&&&&&&&&static&void&Main(string[]&args)
&&&&&&&&&&&&Mutex&configFileMutex&=&new&Mutex(false,&"configFileMutex");
&&&&&&&&&&&&Console.WriteLine("Wait&for&configFileMutex&Process&Id&:&"&+&Process.GetCurrentProcess().Id);
&&&&&&&&&&&&configFileMutex.WaitOne();
&&&&&&&&&&&&Console.WriteLine("Enter&configFileMutex&Process&Id&:&"&+&Process.GetCurrentProcess().Id);
&&&&&&&&&&&&System.Threading.Thread.Sleep(<span style="color: #000);
&&&&&&&&&&&&if&(!File.Exists(@".\config.txt"))
&&&&&&&&&&&&{
&&&&&&&&&&&&&&&&FileStream&stream&=&File.Create(@".\config.txt");
&&&&&&&&&&&&&&&&StreamWriter&writer&=&new&StreamWriter(stream);
&&&&&&&&&&&&&&&&writer.WriteLine("This&is&a&Test!");
&&&&&&&&&&&&&&&&writer.Close();
&&&&&&&&&&&&&&&&stream.Close();
&&&&&&&&&&&&}
&&&&&&&&&&&&else
&&&&&&&&&&&&{
&&&&&&&&&&&&&&&&String[]&lines&=&File.ReadAllLines(@".\config.txt");
&&&&&&&&&&&&&&&&for&(int&i&=&<span style="color: #;&i&&&lines.L&i++)
&&&&&&&&&&&&&&&&&&&&Console.WriteLine(lines[i]);
&&&&&&&&&&&&}
&&&&&&&&&&&&configFileMutex.ReleaseMutex();
&&&&&&&&&&&&configFileMutex.Close();
&&&&&&&&&&&
运行截图如下
此时,PID 为 4628的进程正在等待PID&为 3216的进程释放configFileMutex的互斥体,因此它阻塞在WaitOne函数中,当PID为3216的进程添加并写入了一条信息
至config.txt文件后,释放configFileMutex的独占权,PID为4628的进程获取configFileMutex的独占权,并从config.txt文件中读取输出PID3216进程写入的信息,截图如下
可见使用Mutex进行同步,同步的互斥体是存在于多个进程间的。
&&&&&&&&&&& 6. 使用System.Threading.ReaderWriterLock类实现多用户读/单用户写的同步访问机制
&&&&&&&&&&&&&&& 在考虑资源访问的时候,惯性上我们会对资源实施lock机制,但是在某些情况下,我们仅仅需要读取资源的数据,而不是修改资源的数据,在这种情况下获取资源的独占权无疑会影响运行效率,因此.Net提供了一种机制,使用ReaderWriterLock进行资源访问时,如果在某一时刻资源并没有获取写的独占权,那么可以获得多个读的访问权,单个写入的独占权,如果某一时刻已经获取了写入的独占权,那么其它读取的访问权必须进行等待,参考以下代码
&&&&&&&&&&&&&
using&System.Collections.G
using&System.T
using&System.T
using&System.IO;
using&System.D
namespace&MonitorApplication
&&&&class&Program
&&&&&&&&private&static&ReaderWriterLock&m_readerWriterLock&=&new&ReaderWriterLock();
&&&&&&&&private&static&int&m_int&=&<span style="color: #;
&&&&&&&&static&void&Main(string[]&args)
&&&&&&&&&&&&Thread&readThread&=&new&Thread(Read);
&&&&&&&&&&&&readThread.Name&=&"ReadThread1";
&&&&&&&&&&&&Thread&readThread2&=&new&Thread(Read);
&&&&&&&&&&&&readThread2.Name&=&"ReadThread2";
&&&&&&&&&&&&Thread&writeThread&=&new&Thread(Writer);
&&&&&&&&&&&&writeThread.Name&=&"WriterThread";
&&&&&&&&&&&&readThread.Start();
&&&&&&&&&&&&readThread2.Start();
&&&&&&&&&&&&writeThread.Start();
&&&&&&&&&&&&readThread.Join();
&&&&&&&&&&&&readThread2.Join();
&&&&&&&&&&&&writeThread.Join();
&&&&&&&&private&static&void&Read()
&&&&&&&&&&&&while&(true)
&&&&&&&&&&&&{
&&&&&&&&&&&&&&&&Console.WriteLine("ThreadName&"&+&Thread.CurrentThread.Name&+&"&AcquireReaderLock");
&&&&&&&&&&&&&&&&m_readerWriterLock.AcquireReaderLock(<span style="color: #000);
&&&&&&&&&&&&&&&&Console.WriteLine(String.Format("ThreadName&:&{0}&&m_int&:&{1}",&Thread.CurrentThread.Name,&m_int));
&&&&&&&&&&&&&&&&m_readerWriterLock.ReleaseReaderLock();
&&&&&&&&&&&&}
&&&&&&&&private&static&void&Writer()
&&&&&&&&&&&&while&(true)
&&&&&&&&&&&&{
&&&&&&&&&&&&&&&&Console.WriteLine("ThreadName&"&+&Thread.CurrentThread.Name&+&"&AcquireWriterLock");
&&&&&&&&&&&&&&&&m_readerWriterLock.AcquireWriterLock(<span style="color: #00);
&&&&&&&&&&&&&&&&Interlocked.Increment(ref&m_int);
&&&&&&&&&&&&&&&&Thread.Sleep(<span style="color: #00);
&&&&&&&&&&&&&&&&m_readerWriterLock.ReleaseWriterLock();
&&&&&&&&&&&&&&&&Console.WriteLine("ThreadName&"&+&Thread.CurrentThread.Name&+&"&ReleaseWriterLock");
&&&&&&&&&&&&}
在程序中,我们启动两个线程获取m_int的读取访问权,使用一个线程获取m_int的写入独占权,执行代码后,输出如下
可以看到,当WriterThread获取到写入独占权后,任何其它读取的线程都必须等待,直到WriterThread释放掉写入独占权后,才能获取到数据的访问权,
应该注意的是,上述打印信息很明显显示出,可以多个线程同时获取数据的读取权,这从ReadThread1和ReadThread2的信息交互输出可以看出。
&&&&&&&& 7.使用System.Runtime.Remoting.Contexts.SynchronizationAttribute对类对象进行同步控制
&&&&&&&&&&& 当我们确定某个类的实例在同一时刻只能被一个线程访问时,我们可以直接将类标识成Synchronization的,这样,CLR会自动对这个类实施同步机制,
实际上,这里面涉及到同步域的概念,当类按如下设计时,我们可以确保类的实例无法被多个线程同时访问
&&&&&&&&&&&&&&&&&&&&& 1).&在类的声明中,添加System.Runtime.Remoting.Contexts.SynchronizationAttribute属性。
&&&&&&&&&&&&&&&&&&&&& 2). 继承至System.ContextBoundObject
&&&&&&&&&&&&需要注意的是,要实现上述机制,类必须继承至System.ContextBoundObject,换句话说,类必须是上下文绑定的.
&&&&&&&&&&& 一个示范类代码如下
&&&&&&&&&&&
&[System.Runtime.Remoting.Contexts.Synchronization]
&public&class&SynchronizedClass&:&System.ContextBoundObject
&&&&&&&&&&& 还有AutoResetEvent,ManualReset,EventWaitHandle,Semaphore等可以实现资源的控制,不过它们更多是是基于一种事件唤醒的机制,
如果有兴趣可以查阅MSDN相关的文档。
&&&&&&&&&&& 小弟我刚进入Net学习没多久,写得有什么地方不好,欢迎各位大侠多提意见,希望能与更多的人一起交流,学习
&&&&&&&&&&&&
阅读(...) 评论()

我要回帖

更多关于 从西十区买到赠票 的文章

 

随机推荐