线程基础篇-线程同步
Lock是将一段代码定义为临界区,临界区中的代码在同一时刻只能有一个线程访问,当临界区代码执行时,其他线程调用会被阻塞,需等待资源释放。
语法:
private object locker=new object();
void Method()
{
lock(locker)
{
代码块…
}
}
注意:
1 lock不能锁定空值
2 lock不能string类型,因为字符驻留机制,无法被释放
3 lock不能锁定值类型
4 lock避免锁定public类型或不受程序控制的对象,容易出现死锁
实例
基础类
class CTest{private bool deadlocked = true;private object locker = new object();public void LockMe(object o){lock(locker){while(deadlocked){deadlocked=(bool)o;Console.WriteLine("Foo:I am locked :(");Thread.Sleep(500);}}}public void DoNotLockMe(){Console.WriteLine("I am not locked:)");}}
操作
static void Main(string[] args){CTest c1 = new CTest();Thread th = new Thread(c1.LockMe);th.Start(true);Thread.Sleep(100);lock (c1){c1.DoNotLockMe();c1.LockMe(false);}Console.ReadKey();}
显示效果:
Monitor
lcok的底层是Monitor.Enter和Moniter.Exit,有了lock语法糖可以轻松实现加锁操作,为了更精确的操作,需要使用Monitor类
Monitor.Enter 上锁,锁定资源
Monitor.TryEnter 在指定超时时间内锁定资源,可避免死锁
Monitor.Wait 暂时释放资源
Monitor.Pulse 唤醒等待队列中的线程
Monitor.Exit 释放资源
实例:
打印奇偶数方法
public void PrintEven(){Monitor.Enter(this);try{for(i=0 ;i<=10;i=i+2){Console.WriteLine(Thread.CurrentThread.Name+"-----"+i);}}Catch(Exception){throw;}finally{Monitor.Exit(this);}}public void PrintOdd(){Monitor.Enter(this);try{for(i=1;i<=10;i=i+2){Console.WriteLine(Thread.CurrentThread.Name+"----"+i);}catch(Exception){throw;}finally{Monitor.Exit(this);}}}
操作
static void Main(string[] args){Program p = new Program();Thread the = new Thread(p.PrintEven);the.IsBackground=true;the.Name="打印偶数";the.Start();Thread tho = new Thread(p.PrintOdd);tho.IsBackground=true;tho.Name="打印奇数";tho.Start();Console.ReadKey();}
显示效果:
ReaderWriterLock
主要解决类似数据库这种读取数据多写入数据少的情况,如用Monitor类则形成独占,不能实现多个线程读取数据,读写锁很好的解决了这一情况
主要包括以下几个方法:
AcquireReaderLock 获取读取锁
ReleaseReaderLock 释放读取锁
AcquireWriterLock 获取写入锁
ReleaseWriterLock 释放写入锁
UpgradeToWriterLock 读锁转换为写锁
DowngradeFromWriterLock 写锁转换为读锁
Mutex
跨多个线程同步访问的类,只有一个线程能获得互斥锁定,访问受互斥保护的同步代码区域。
WaitOne 等待资源释放
ReleaseMutex 释放资源
最常用的是程序启动时判断是否已有实例在运行
代码如下:
static void Main(){bool flag = false;bool requestInitialOwnership = true;Mutex mt = new Mutex(requestInitialOwnership, "MutexTest1", out flag);if (flag){Application.EnableVisualStyles();Application.SetCompatibleTextRenderingDefault(false);Application.Run(new Form1());}else{MessageBox.Show("MutexTest1已启动");Application.Exit();}}
显示效果:
排队买票,同一窗口在同一时间只能有一个人买票
买票方法
private static Mutex mt = new Mutex();public static void BuyTickets(Object name){if(mt.WaitOne()){try{Console.WriteLine("{0}占用窗口并开始买票",name);Thread.Sleep(1000);}catch(Exception){throw;}finally{Console.WriteLine("{0}离开窗口",name);mt.ReleaseMutex();}}}
操作
static void Main(){Thread th1 = new Thread(BuyTickets);th1.Start("小明");Thread th2 = new Thread(BuyTickets);th2.Start("小A");Console.ReadKey();}
显示效果:
Interlocked
为多线程共享整数变量提供原子操作,类似操作系统的PV操作
Interlocked.Read 读取计数器的值
Interlocked.Add 使计数器增加指定的值
Interlocked.Increment 使计数器加一
Interlocked.Decrement 使计数器减一
Interlocked.Exchange 把计数器设定为某个指定值
Interlocked.CompareExchange 将计数器与某个值比较,若相等则计数器设定为指定的值
实例
private static char buffer;private static long used = 0;static void Main(string[] args){string str = "壬戌之秋,七月既望,苏子与客泛舟游于赤壁之下。清风徐来,水波不兴。举酒属客,诵明月之诗,歌窈窕之章。";Thread thWriter=new Thread(delegate(){for (int i = 0; i < str.Length; i++){while (Interlocked.Read(ref used) == 1){Thread.Sleep(50);}buffer = str[i];Interlocked.Increment(ref used);}});Thread thReader = new Thread(delegate (){for (int i = 0; i < str.Length; i++){while (Interlocked.Read(ref used) == 0){Thread.Sleep(50);}char ch = buffer;Console.Write(ch);Interlocked.Decrement(ref used);}});thWriter.Start();thReader.Start();Console.ReadKey();}
显示效果:文字会一个一个的打印出来,并且不会乱。
AutoResetEvent ManualResetEvent
实现线程通信,类似信号量Semaphore
Set() 将信号状态设置为有信号
Reset() 将信号状态设置为无信号
WaitOne() 无信号时线程阻塞,有信号时线程无阻塞
AutoResetEvent和ManualResetEvent的区别在于WaitOne方法,AutoResetEvent的WaitOne会自动改变事件对象的状态,每次只能唤醒一个线程。
线程基础篇-线程同步相关推荐
- linux线程基础篇----线程同步与互斥
linux线程基础----线程同步与互斥 一.同步的概念 1.同步概念 所谓同步,即同时起步,协调一致.不同的对象,对"同步"的理解方式略有不同.如,设备同步,是指在两个设备 ...
- Java中的线程基础篇-线程基本概念
线程的概念.创建方式.生命周期.优缺点 一.基础知识 1. 进程.线程.协程 1.1 进程 1.2 线程 1.3 协程 2. 串行.并发.并行 2.1 串行 2.2 并发 2.3 并行 二.线程的创建 ...
- 关于java线程同步的笔记_线程同步(JAVA笔记-线程基础篇)
在多线程应用程序中经常会遇到线程同步的问题.比如:两个线程A.线程B可能会 "同时" 执行同一段代码,或修改同一个变量.而很多时候我们是不希望这样的. 这时候,就需要用到线程同步. ...
- 【Java_多线程并发编程】基础篇—线程状态及实现多线程的两种方式
1.Java多线程的概念 同一时间段内,位于同一处理器上多个已开启但未执行完毕的线程叫做多线程.他们通过轮寻获得CPU处理时间,从而在宏观上构成一种同时在执行的假象,实质上在任意时刻只有一个线程获得C ...
- JavaEE-多线程(基础篇一)
文章目录 线程是啥?!(Thread) Java的线程与操作系统线程的关系 操作系统线程模型 线程-在用户空间下实现 线程实现在操作系统内核中 使用用户线程更加轻量级进程混合实现 Java线程 Jav ...
- JAVA从入门到精通------基础篇------线程
1.什么是进程 程序是静止的,只有真正运行时的程序才能被称为进程 举个例子,我们的每一个软件就是一个进程 单核CPU在任何时间点上,只能运行一个进程,宏观并行,微观串行 2.什么是线程 线程,又称轻量 ...
- java线程基础巩固---线程生命周期以及start方法源码剖析
上篇中介绍了如何启动一个线程,通过调用start()方法才能创建并使用新线程,并且这个start()是非阻塞的,调用之后立马就返回的,实际上它是线程生命周期环节中的一种,所以这里阐述一下线程的一个完整 ...
- java 线程 操作系统线程_线程基础:线程(1)——操作系统和线程原理
1.概述 我在写"系统间通信技术专栏"的时候,收到很多读者的反馈.其中有一部分读者希望我抽空写一写自己关于对Java线程的使用经验和总结.巧的是,这个月我所在的技术团队也有很多同事 ...
- 多线程与高并发(一):单机高并发应该掌握的线程基础:线程状态,异常与锁等
多线程复习 多线程的基本概念 什么是一个线程?如何开启一个线程? package com.mashibing.juc.c_000;import java.util.concurrent.TimeUni ...
最新文章
- 怎么git 自己建的服务器_Git服务器搭建,以及Git基本操作
- 视频检测人脸添加帽子完美方案
- 西安交通大学17年9月课程考试计算机应用基础,西安交通大学17年9月课程考试《计算机应用基础》作业考核试题 (含主观题)...
- pika集群水平扩展——让性能容量不再受限
- sybase不支持的条件表达式_包教包会!7段代码带你玩转Python条件语句(附代码)...
- 获取一些系统和用户的通用属性
- C语言函数传入字母参数,c语言详细讲解函数参数作为数组传递的几种方式
- QT造类器(操作简单)
- 智能制造与大数据——数据采集实现数字化
- 【开篇】初等数论及其核心内容
- 谷歌浏览器利用开发者工具截取长图
- 计算机毕业设计JAVA企业售后服务管理系统mybatis+源码+调试部署+系统+数据库+lw
- 如果你是12306网站架构师,你会如何设计网站的软件架构和硬件系统架构?
- Apollo配置说明
- 100.64.0.0/10 运营商级NAT(Carrier-grade NAT)共享地址空间
- 华为Nova 4 HL1VCEM (VCE-L22/VCE-AL00)手机图纸电路原理图+主板高清图片
- Board (染色思想)
- 基于PSINS工具箱的卡尔曼滤波与SINS/GNSS组合导航
- 自己对win10虚拟内存的理解,不一定对
- RocksDB 介绍
热门文章
- linux usb3 转hdmi,USB TYPE-C转HDMI+PD3.0+USB3.0/USB3.1多功能扩展坞设计方法和设计电路...
- 火狐(firefox)调试移动端页面
- C语言编程精髓读书笔记(怎样有效地使用断言和避免自由主义编码)
- 2020年计算机双非保研经历分享(2021届)
- R语言1——R的安装和相关介绍
- [转]UML八大误解
- python Dataframe 根据某一列的值来删除多行
- python银行账户资金交易管理办法_Python实现银行账户资金交易管理系统
- 项目需求分析和项目可行性
- CXF系列(四):CXF整合spring