PS:小编之前毕业找工作面试的公司,基本上每家公司都有提问到多线程,而多线程在大学里基本上都是没有涉及,或者涉及不深,又或者平时的自主练习基本没有涉及这块的内容,因此这个多线程系列是面试前必须要掌握的,临时抱佛脚也是可以的(就目前来说,多线程在大公司里面都是封装好的,基本上就是学习使用的问题,但是多线程的基本知识还是要了解的)
public void test(int i)
{
lock(this)
{
if (i>10)
{
i--;
test(i);
}
}
}
不会发⽣死锁,(但有⼀点int是按值传递的,所以每次改变的都只是⼀个副本,因此不会出现死锁。但如果把int换做⼀个object,那么死锁会发⽣)
线程(Thread)与进程(Process)⼆者都定义了某种边界,不同的是进程定义的是应⽤程序与应⽤程序之间的边界,不同的进程之间不能共享代码和数据空间,⽽线程定义的是代码执⾏堆栈和执⾏上下⽂的边界。⼀个进程可以包括若⼲个线程,同时创建多个线程来完成某项任务,便是多线程。
⽽同⼀进程中的不同线程共享代码和数据空间。⽤⼀个⽐喻来说,如果⼀个家庭代表⼀个进程,在家庭内部,各个成员就是线程,家庭中的每个成员都有义务对家庭的财富进⾏积累,同时也有权利对家庭财富进⾏消费,当⾯对⼀个任务的时候,家庭也可以派出⼏个成员来协同完成,⽽家庭之外的⼈则没有办法直接消费不属于⾃⼰家庭的财产。
这个需要针对硬件平台,公式为单个进程能访问的最⼤内存量=2的处理器位数次⽅/2,⽐如通常情况下,32位处理器下,单个进程所能访问的最⼤内存量为:232 /2 = 2G 。单个进程能访问的最⼤内存量是最⼤虚拟内存的1/2,因为要分配给操作系统⼀半虚拟内存。
有⽤,实现了IDisposiable的类在using中创建,using结束后会⾃定调⽤该对象的Dispose⽅法,释放资源。
通过将 Thread.IsBackground 属性设置为 true,就可以将线程指定为后台线程
前台线程: 应⽤必须结束掉所有的前台线程才能结束程序,只要有⼀个前台线程没退出进程就不会⾃动退出,当然线程是依附在进程上的,所以你直接把进程KO掉了的话⾃然所有前台线程也会退出。
后台线程: 进程可以不考虑后台直接⾃动退出,进程⾃动退出后所有的后台线程也会⾃动销毁。
当多个线程访问同⼀个全局变量,或者同⼀个资源(⽐如打印机)的时候,需要进⾏线程间的互斥操作来保证访问的安全性。
线程池的线程数是有限制的,通常情况下,我们⽆需修改默认的配置。但在⼀些场合,我们可能需要了解线程池的上下限和剩余的线程数。线程池作为⼀个缓冲池,有着其上下限。在通常情况下,当线程池中的线程数⼩于线程池设置的下限时,线程池会设法创建新的线程,⽽当线程池中的线程数⼤于线程池设置的上限时,线程池将销毁多余的线程。
PS:在.NET Framework 4.0中,每个CPU默认的⼯作者线程数量最⼤值为250个,最⼩值为2个。⽽IO线程的默认最⼤值为1000个,最⼩值为2个。
在.NET中,通过 ThreadPool 类型提供的5个静态⽅法可以获取和设置线程池的上限和下限,同时它还额外地提供了⼀个⽅法来让程序员获知当前可⽤的线程数量,下⾯是这五个⽅法的签名:
① static void GetMaxThreads(out int workerThreads, out int completionPortThreads)
② static void GetMinThreads(out int workerThreads, out int completionPortThreads)
③ static bool SetMaxThreads(int workerThreads, int completionPortThreads)
④ static bool SetMinThreads(int workerThreads, int completionPortThreads)
⑤ static void GetAvailableThreads(out int workerThreads, out int completionPortThreads)
CPS全称是Continuation Passing Style,在.NET中,它会⾃动编译为: 1. 将所有引⽤的局部变量做成闭包,放到⼀个隐藏的状态机的类中; 2. 将所有的await展开成⼀个状态号,有⼏个await就有⼏个状态号; 3. 每次执⾏完⼀个状态,都重复回调状态机的MoveNext⽅法,同时指定下⼀个状态号; 4.
MoveNext⽅法还需处理线程和异常等问题。
从状态机的⻆度出发,await的本质是调⽤Task.GetAwaiter()的UnsafeOnCompleted(Action)回调,并指定下⼀个状态号。
从多线程的⻆度出发,如果await的Task需要在新的线程上执⾏,该状态机的MoveNext()⽅法会⽴即返回,此时,主线程被释放出来了,然后在UnsafeOnCompleted回调的action指定的线程上下⽂中继续MoveNext()和下⼀个状态的代码。
⽽相⽐之下,GetResult()就是在当前线程上⽴即等待Task的完成,在Task完成前,当前线程不会释放。注意:Task也可能不⼀定在新的线程上执⾏,此时⽤GetResult()或者await就只有会不会创建状态机的区别了。
Task和Thread都能创建⽤多线程的⽅式执⾏代码,但它们有较⼤的区别。Task较新,发布于.NET 4.5,能结合新的async/await代码模型写代码,它不⽌能创建新线程,还能使⽤线程池(默认)、单线程等⽅式编程,在UI编程领域,Task还能⾃动返回UI线程上下⽂,还提供了许多便利API以管理多个Task。
(1)发挥多核CPU的优势
随着⼯业的进步,现在的笔记本、台式机乃⾄商⽤的应⽤服务器⾄少也都是双核的,4核、8核甚⾄16核的也都不少⻅,如果是单线程的程序,那么在双核CPU上就浪费了50%,在4核CPU上就浪费了75%。单核CPU上所谓的”多线程”那是假的多线程,同⼀时间处理器只会处理⼀段逻辑,只不过线程之间切换得⽐较快,看着像多个线程”同时”运⾏罢了。多核CPU上的多线程才是真正的多线程,它能让你的多段逻辑同时⼯作,多线程,可以真正发挥出多核CPU的优势来,达到充分利⽤CPU的⽬的。
(2)防⽌阻塞
从程序运⾏效率的⻆度来看,单核CPU不但不会发挥出多线程的优势,反⽽会因为在单核CPU上运⾏多线程导致线程上下⽂的切换,⽽降低程序整体的效率。但是单核CPU我们还是要应⽤多线程,就是为了防⽌阻塞。试想,如果单核CPU使⽤单线程,那么只要这个线程阻塞了,⽐⽅说远程读取某个数据吧,对端迟迟未返回⼜没有设置超时时间,那么你的整个程序在数据返回回来之前就停⽌运⾏了。多线程可以防⽌这个问题,多条线程同时运⾏,哪怕⼀条线程的代码执⾏读取数据阻塞,也不会影响其它任务的执⾏。
(3)便于建模
这是另外⼀个没有这么明显的优点了。假设有⼀个⼤的任务A,单线程编程,那么就要考虑很多,建⽴整个程序模型⽐较麻烦。但是如果把这个⼤的任务A分解成⼏个⼩任务,任务B、任务C、任务D,分别建⽴程序模型,并通过多线程分别运⾏这⼏个任务,那就简单很多了。
这道题就是说有两个线程,⼀个名为偶数线程,⼀个名为奇数线程,偶数线程只打印偶数,奇数线程只打印奇数,两个线程按顺序交替打印。
1 publicclassThreadExample
2 {
3 ///<summary>
4 ///两个线程交替打印0~100的奇偶数
5 ///</summary>
6 public static void PrintOddEvenNumber
7 {
8 varwork = newTheadWorkTest;
9 varthread1 = newThread(work.PrintOddNumer) { Name = "奇数线程"};
10 varthread2 = newThread(work.PrintEvenNumber) { Name = "偶数线
程"};
11 thread1.Start;
12 thread2.Start;
13 }
14 }
15
16 publicclassTheadWorkTest
17 {
18
19 privatestaticreadonlyAutoResetEvent oddAre = newAutoResetEvent(
false);
20
21 privatestaticreadonlyAutoResetEvent evenAre = newAutoResetEvent
( false);
22
23 publicvoidPrintOddNumer
24 {
25 oddAre.WaitOne;
26 for( var0; i < 100; i++ )
27 {
28 if(i % 2!= 1) continue;
29 Console.WriteLine($"{Thread.CurrentThread.Name}:{i}");
30 evenAre.Set;
31 oddAre.WaitOne;
32 }
33 }
34
35 publicvoidPrintEvenNumber
36 {
37 for( vari = 0; i < 100; i++ )
38 {
39 if(i % 2!= 0) continue;
40 Console.WriteLine($"{Thread.CurrentThread.Name}:{i}");
41 oddAre.Set;
42 evenAre.WaitOne;
43 }
44 }
45 }
因为GUI应⽤程序引⼊了⼀个特殊的线程处理模型,为了保证UI控件的线程安全,这个线程处理模型不允许
其他⼦线程跨线程访问UI元素。解决⽅法⽐较多的:
常⽤的如如SemaphoreSlim、ManualResetEventSlim、Monitor、ReadWriteLockSlim,lock是⼀个混合锁,其实质是Monitor
lock的锁对象要求为⼀个引⽤类型。她可以锁定值类型,但值类型会被装箱,每次装箱后的对象都不⼀样,会导致锁定⽆效。
对于lock锁,锁定的这个对象参数才是关键,这个参数的同步索引块指针会指向⼀个真正的锁(同步块),这个锁(同步块)会被复⽤。
多线程是实现异步的主要⽅式之⼀,异步并不等同于多线程。实现异步的⽅式还有很多,⽐如利⽤硬件的特性、使⽤进程或线程等。
在.NET中就有很多的异步编程⽀持,⽐如很多地⽅都有Begin、End 的⽅法,就是⼀种异步编程⽀持,她内部有些是利⽤多线程,有些是利⽤硬件的特性来实现的异步编程。
优点:减⼩线程创建和销毁的开销,可以复⽤线程;也从⽽减少了线程上下⽂切换的性能损失;在GC回收时,较少的线程更有利于GC的回收效率。缺点:线程池⽆法对⼀个线程有更多的精确的控制,如了解其运⾏状态等;不能设置线程的优先级;加⼊到线程池的任务(⽅法)不能有返回值;对于需要⻓期运⾏的任务就不适合线程池。
Mutex是⼀个基于内核模式的互斥锁,⽀持锁的递归调⽤,⽽Lock是⼀个混合锁,⼀般建议使⽤Lock更好,因为lock的性能更好。
1 public static class Singleton<T> where T : class,new()
2 {
3 private static T _Instance;
4 private static object _lockObj = new object();
5
6 /// <summary>
7 /// 获取单例对象的实例
8 /// </summary>
9 public static T GetInstance()
10 {
11 if (_Instance != null) return _Instance;
12 lock (_lockObj)
13 {
14 if (_Instance == null)
15 {
16 var temp = Activator.CreateInstance<T>();
17 System.Threading.Interlocked.Exchange(ref _In
stance, temp);
18 }
19 }
20 return _Instance;
21 }
22 }
属性:
⽅法:
public void Abort()
在调⽤此⽅法的线程上引发 ThreadAbortException,以开始终⽌此线程的过程。调⽤此⽅法通常会终⽌线程。
public static void ResetAbort()//取消为当前线程请求的 Abort。
public void Start() 开始⼀个线程。
public static void Sleep( int millisecondsTimeout )//让线程暂停⼀段时间。
public static bool Yield()//导致调⽤线程执⾏准备好在当前处理器上运⾏的另⼀个线程。由操作系统选择要执⾏的线程。
作为我的Rails应用程序的一部分,我编写了一个小导入程序,它从我们的LDAP系统中吸取数据并将其塞入一个用户表中。不幸的是,与LDAP相关的代码在遍历我们的32K用户时泄漏了大量内存,我一直无法弄清楚如何解决这个问题。这个问题似乎在某种程度上与LDAP库有关,因为当我删除对LDAP内容的调用时,内存使用情况会很好地稳定下来。此外,不断增加的对象是Net::BER::BerIdentifiedString和Net::BER::BerIdentifiedArray,它们都是LDAP库的一部分。当我运行导入时,内存使用量最终达到超过1GB的峰值。如果问题存在,我需要找到一些方法来更正我的代
关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。
是的,我知道最好使用webmock,但我想知道如何在RSpec中模拟此方法:defmethod_to_testurl=URI.parseurireq=Net::HTTP::Post.newurl.pathres=Net::HTTP.start(url.host,url.port)do|http|http.requestreq,foo:1endresend这是RSpec:let(:uri){'http://example.com'}specify'HTTPcall'dohttp=mock:httpNet::HTTP.stub!(:start).and_yieldhttphttp.shou
这里是Ruby新手。完成一些练习后碰壁了。练习:计算一系列成绩的字母等级创建一个方法get_grade来接受测试分数数组。数组中的每个分数应介于0和100之间,其中100是最大分数。计算平均分并将字母等级作为字符串返回,即“A”、“B”、“C”、“D”、“E”或“F”。我一直返回错误:avg.rb:1:syntaxerror,unexpectedtLBRACK,expecting')'defget_grade([100,90,80])^avg.rb:1:syntaxerror,unexpected')',expecting$end这是我目前所拥有的。我想坚持使用下面的方法或.join,
我收到这个错误:RuntimeError(自动加载常量Apps时检测到循环依赖当我使用多线程时。下面是我的代码。为什么会这样?我尝试多线程的原因是因为我正在编写一个HTML抓取应用程序。对Nokogiri::HTML(open())的调用是一个同步阻塞调用,需要1秒才能返回,我有100,000多个页面要访问,所以我试图运行多个线程来解决这个问题。有更好的方法吗?classToolsController0)app.website=array.join(',')putsapp.websiteelseapp.website="NONE"endapp.saveapps=Apps.order("
我目前正在使用以下方法获取页面的源代码:Net::HTTP.get(URI.parse(page.url))我还想获取HTTP状态,而无需发出第二个请求。有没有办法用另一种方法做到这一点?我一直在查看文档,但似乎找不到我要找的东西。 最佳答案 在我看来,除非您需要一些真正的低级访问或控制,否则最好使用Ruby的内置Open::URI模块:require'open-uri'io=open('http://www.example.org/')#=>#body=io.read[0,50]#=>"["200","OK"]io.base_ur
在应用开发中,有时候我们需要获取系统的设备信息,用于数据上报和行为分析。那在鸿蒙系统中,我们应该怎么去获取设备的系统信息呢,比如说获取手机的系统版本号、手机的制造商、手机型号等数据。1、获取方式这里分为两种情况,一种是设备信息的获取,一种是系统信息的获取。1.1、获取设备信息获取设备信息,鸿蒙的SDK包为我们提供了DeviceInfo类,通过该类的一些静态方法,可以获取设备信息,DeviceInfo类的包路径为:ohos.system.DeviceInfo.具体的方法如下:ModifierandTypeMethodDescriptionstatic StringgetAbiList()Obt
1.错误信息:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:requestcanceledwhilewaitingforconnection(Client.Timeoutexceededwhileawaitingheaders)或者:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:TLShandshaketimeout2.报错原因:docker使用的镜像网址默认为国外,下载容易超时,需要修改成国内镜像地址(首先阿里
基础版云数据库RDS的产品系列包括基础版、高可用版、集群版、三节点企业版,本文介绍基础版实例的相关信息。RDS基础版实例也称为单机版实例,只有单个数据库节点,计算与存储分离,性价比超高。说明RDS基础版实例只有一个数据库节点,没有备节点作为热备份,因此当该节点意外宕机或者执行重启实例、变更配置、版本升级等任务时,会出现较长时间的不可用。如果业务对数据库的可用性要求较高,不建议使用基础版实例,可选择其他系列(如高可用版),部分基础版实例也支持升级为高可用版。基础版与高可用版的对比拓扑图如下所示。优势 性能由于不提供备节点,主节点不会因为实时的数据库复制而产生额外的性能开销,因此基础版的性能相对于
目录第1题连续问题分析:解法:第2题分组问题分析:解法:第3题间隔连续问题分析:解法:第4题打折日期交叉问题分析:解法:第5题同时在线问题分析:解法:第1题连续问题如下数据为蚂蚁森林中用户领取的减少碳排放量iddtlowcarbon10012021-12-1212310022021-12-124510012021-12-134310012021-12-134510012021-12-132310022021-12-144510012021-12-1423010022021-12-154510012021-12-1523.......找出连续3天及以上减少碳排放量在100以上的用户分析:遇到这类