线程

一个自旋锁的栗子

大兔子大兔子 提交于 2020-03-21 17:27:13
  一直以来不是怎么清楚自旋锁,最近有点时间,好好的学习了一下;   所谓的自旋锁在我的理解就是多个线程在尝试获取锁的时候,其中一个线程获取锁之后,其他的线程都处在一直尝试获取锁的状态,不会阻塞!!!那么什么叫做一直尝试获取锁呢?就是一个循环,比较经典的是AtomicInteger中的一个updateAndGet方法,下图所示(当然也可以直接看unsafe类中的getAndAddInt等类似方法);   我们可以看出在while循环中使用CAS去尝试更新一个变量,如果更新失败,就会一直在这个循环中一直在尝试;成功的话,就可以到最后的return语句;   由此我们可以大概知道如果自旋的线程过多,那么CPU的资源就会被大量消耗!!!   顺便提一个东西叫做原子引用,官方提供了AtomicInteger,AtomicBoolean等原子类,那么如果我们自己定义的类也需要有原子性怎么办呢?所以官方提供了一个AtomicReference类,可以将我们自己定义的类封装一下,就成了我们自己的原子类,例如AtomicReference<Student> atomicReference = new AtomicReference<>();,然后我们对Student的实例进行CAS各种CAS操作;   栗子: package TestMain; import lombok.extern.slf4j

Python学习记录

爷,独闯天下 提交于 2020-03-21 16:47:37
Python学习记录Day1 1.什么是Python? Python的本意其实蟒蛇,由于其创始人为荷兰人吉多·范罗苏姆(Guido van Rossum)喜欢一部电视喜剧《Monty Python's Flying Circus》,故将其命名为Python。而Python的诞生(Python解释器原型)则是因为1989年圣诞期间,Guido为了打发圣诞节的无趣,就决心开发一个新的脚本解释程序,作为ABC语言的一种继承。1991年,第一个Python解释器诞生,它是用C语言实现的,并且能调用C语言的库文件。 1.1什么是解释器? 计算机是不能理解除机器语言之外的任何语言的,所以必须把程序员所写的程序语言翻译为计算机能看懂的机器语言,计算机才能执行程序,将其他语言翻译成机器语言的工具,成为编译器。编译器的翻译方式分为两种:一种为编译,一种为解释。两者翻译的区别在于运行的时间点的不同。当编译器以解释方式运行是,称为解释器。 ●编译型语言:程序在执行之前需要一一个专]的编译过程,把程序编译成为机器语言的文件,运行时不需要重新翻译,直接使用编译的结果就行了。程序执行效率高,依赖编译器,跨平台性差些。如C、C++ ●解释型语言:解释型语言编写的程序不进行预先编译,以文本方式存储程序代码,会将代码句一句直接运行。在发布程序时,看起来省了道编译工序,但是在运行程序的时候,必须先解释再运行

wpf(怎么跨线程访问wpf控件)

谁都会走 提交于 2020-03-21 15:32:46
在编写代码时,我们经常会碰到一些子线程中处理完的信息,需要通知另一个线程(我这边处理完了,该你了)。 但是当我们通知WPF的UI线程时需要用到Dispatcher。 首先我们需要想好在UI控件上需要显示什么内容。然后写一个显示UI内容的方法。 以下是代码 private void UIThreaddosomething(string s) //UI线程要做的事情 { //do something //这里也可以做一些其他的事情 Label2.Content = s; ellipse1.Fill=new SolidColorBrush(Colors.Red); ellipse2.Fill=new SolidColorBrush(Colors.Red); } 然后我们声明一个委托,由于UIThreaddosomething有一个字符串参数,所以声明的委托要与其保持一致 public delegate void RefleshUI(string s); 然后在创建一个方法,这个方法将通过委托将子线程与UI线程联系起来。 private void delegatedosomething(string s) { ellipse1.Dispatcher.Invoke(new RefleshUI(UIThreaddosomething), s); // ellipse2.Dispatcher

CountDownLatch,CyclicBarrier,Semaphore

送分小仙女□ 提交于 2020-03-21 15:25:06
CountDownLatch是倒数,doneSignal = new CountDownLatch(LATCH_SIZE);赋初值后,在主线程中等待doneSignal.await();其它线程中,每完成一个就减一doneSignal.countDown();减到0时主线程继续。 CyclicBarrier是正数,cb = new CyclicBarrier(SIZE);主线程中开启各子线程,子线程调用cb.await()进行等待;cb计数count会加一,等于SIZE时会继续所有等待线程。 Semaphore是信号灯,Semaphore sem = new Semaphore(SEM_MAX);主线程中开启各子线程,子线程调用sem.acquire(count);每调用一次,sem计数会减相应数值,减为0时其它线程再调用acquire时会阻塞,线程结束后记得要sem.release(count); CountDownLatch和Semaphore用的是共享锁,而CyclicBarrier是独占锁。 CountDownLatch只能赋值一次,而CyclicBarrier可赋值多次。 概要 前面对" 独占锁 "和" 共享锁 "有了个大致的了解;本章,我们对CountDownLatch进行学习。 和ReadWriteLock.ReadLock一样

qt中的 connect 函数

一个人想着一个人 提交于 2020-03-21 12:04:47
1、connect()函数实现的是信号与槽的关联。 注意:只有QO bject类及其派生的类才能使用信号和槽的机制 2、函数原型 static QMetaObject::Connection connect(const QObject *sender, const char *signal,const QObject *receiver, const char *member, Qt::ConnectionType = Qt::AutoConnection); static QMetaObject::Connection connect(const QObject *sender, const QMetaMethod &signal,const QObject *receiver, const QMetaMethod &method, Qt::ConnectionType type = Qt::AutoConnection); inline QMetaObject::Connection connect(const QObject *sender, const char *signal,const char *member, Qt::ConnectionType type = Qt::AutoConnection) const; 在第一个函数中:第一个参数为发射信号的对象

浅析 Node.js 单线程模型

江枫思渺然 提交于 2020-03-21 10:24:47
总结笔记:对于每个用户请求,由主线程接收并存放于一个事件队列中(不做任何处理),当无请求发生时,即主线程空闲,主线程开始循环处理事件队列中的任务: 对于非阻塞JS程序: 1、若某事件需要I/O操作,则主线程发出I/O请求,然后继续执行,由底层的程序实现I/O并返回I/O数据(底层程序是多线程的,JS是单线程的),底层I/O线程处理完后将该事件重新放入事件队列并释放当前线程; 2、某事件不需要I/O操作,则主线程直接处理;(由其他线程处理后放入的事件此时也被主线程直接处理掉); 对于阻塞JS程序: 1、若某事件需要I/O操作,则主线程发出I/O请求,然后等待I/O结束,由底层的程序实现I/O并返回I/O数据,主线程获得该事件所需数据后继续处理该事件; 2、某事件不需要I/O操作,则主线程直接处理; 综上可知,node.js由js解释程序和底层代码实现,JS代码是主线程,是单线程执行,而底层代码是多线程,可同时处理多个I/O请求,js中的阻塞与非阻塞代码只决定js在I/O时继不继续执行(当然,若阻塞执行,底层多线程也没啥用了),而底层会为每一个I/O请求创建一个线程; 注意:这只是对Node.js的一个分析,用来理解nodejs的线程模型而已,实际使用要具体问题具体分析,建议结合http://www.runoob.com/nodejs/nodejs-callback

[Python] 多线程相关

落花浮王杯 提交于 2020-03-21 09:48:33
3 月,跳不动了?>>> 1 相关基础 Python3 线程中常用的两个模块为: _thread threading(推荐使用) thread 模块已被废弃。用户可以使用 threading 模块代替。所以,在 Python3 中不能再使用"thread" 模块。为了兼容性,Python3 将 thread 重命名为 "_thread"。 1.1 _thread 模块函数式调用 _thread 提供了低级别的、原始的线程以及一个简单的锁,它相比于 threading 模块的功能还是比较有限的。 函数式:调用 _thread 模块中的start_new_thread()函数来产生新线程。语法如下: _thread.start_new_thread ( function, args[, kwargs] ) 参数说明: function - 线程函数。 args - 传递给线程函数的参数,他必须是个tuple类型。 kwargs - 可选参数。 1.2 threading 模块对象式调用 threading 模块除了包含 _thread 模块中的所有方法外,还提供的其他方法。 除了使用函数外,线程模块同样可以通过直接从 threading.Thread 继承创建一个新的子类,并实例化后调用 start() 方法启动新线程。 import threading import time

用事件队列解决QT GUI的操作顺序问题

我怕爱的太早我们不能终老 提交于 2020-03-21 09:28:50
原文: https://www.cnblogs.com/Philip-Tell-Truth/p/6295186.html GUI操作顺序问题引发异常 有时候我们使用写GUI程序的时候会遇到这样的问题:比如在程序中,建立了一个列表的GUI。这个列表是随着时间不断更新的,而且操作也会读取这个列表GUI的内容。 如果这个程序是多线程的程序,而且只是除了GUI的线程不操作,只是其他线程操作这个列表GUI,那么这个问题很简单,只用加互斥锁就可以了。但如果GUI线程自己本身也要操作这个列表,那么这个问题就很麻烦了。 我们可以很容易地想到一种场景,比如GUI线程读了列表的一些表项(比如选定),此时线程中的某个方法keep了这些表项的指针,然而此时很不幸别的线程有一个请求需要删除列表中的一些表项,并且这些表项有一些包含在了我们的选定内容里,我们知道几乎所有的语言操作GUI时都要进入GUI线程里面操作,那么我们刚才选定表项的那个方法会被打断,然后进入删除表项方法,在删除了表项以后再次回到选定表项方法时,我们的选定的表项有一些已经被删除了,此时我们再进行操作很有可能不符合我们的要求。 如果你是用一般是用C#,JAVA这种不用自己管理内存的语言,那还好,只是结果可能不对,但是如果是用C++这种需要我们自己管理内存的来写,很有可能我们会操作一个被释放了内存的对象,然后程序崩掉,这样的情况是我们不想看到的。

死磕 java线程系列之终篇

假装没事ソ 提交于 2020-03-21 09:06:17
(手机横屏看源码更方便) 简介 线程系列我们基本就学完了,这一个系列我们基本都是围绕着线程池在讲,其实关于线程还有很多东西可以讲,后面有机会我们再补充进来。当然,如果你有什么好的想法,也可以公从号右下角联系我。 重要知识点 直接上图,看着这张图我相信你能够回忆起很多东西,也可以看着这张图来自己提问自己回答,当然,也可以把这张图作为面试复习的参考。 其中,ThreadLocal是我们没有分析的类,放在netty系列来学习,敬请期待^^ 彩蛋 下一个系列我们将学习netty相关的知识,当然跑不掉的还有nio。 我为什么直接讲netty了呢? 因为netty很重要,很多框架的底层都是用netty实现的,比如dubbo、spark、hadoop、storm、zookeeper、grpc、flink、thrift、elasticsearch、spring cloud gateway。 只要牵涉到网络通信的框架,基本上都会使用netty作为底层通信,所以,你说netty重不重要,那是相当的重要,so,我们先讲netty。 我为什么不讲spring系列呢? spring系列主要分为三大部分:spring core、spring boot、spring cloud。 spring core主要包含两大功能:spring IoC和spring mvc,这两个功能其实都是比较简单的东西

各种锁

时光毁灭记忆、已成空白 提交于 2020-03-21 02:12:08
互斥锁(线程锁) 1.为什么要使用互斥锁? 线程之间共享资源,这就导致了多个线程之间资源竞争的问题 2.好处和坏处? 好处:保证了同一时间只允许一个线程的完整执行 坏处:阻止了线程的并发执行,效率降低 由于可以存在多个锁,不同的线程持有不同的锁,并获取对方的锁,可能会造成死锁 import threading # 创建锁 mutex = threading.Lock() # 锁定 mutex.acquire() #释放 mutex.release() 死锁 在线程间共享多个资源时,如果两个线程分别占有一部分资源,并且同时等待对方的资源,就会造成死锁 避免死锁 程序设计时尽量避免(银行家算法) 添加超时时间 乐观锁 乐观锁是相对悲观锁而言的,乐观锁假设数据一般情况下不会造成冲突,所以在数据进行提交更新的时候,才会正式对数据的冲突与否进行检测 乐观锁实现流程: 我们在更新之前,先查询一下库存表中当前库存数(quantity),然后在做update的时候,以库存数作为一个修改条件。 当我们提交更新的时候,判断数据库表对应记录的当前库存数与第一次取出来的库存数进行比对,如果数据库表当前库存数与第一次取出来的库存数相等,则予以更新,否则认为是过期数据。 悲观锁 当我们要对数据库的一条数据进行修改时,为了避免同时被其他人修改,最好的办法就是对该数据进行加锁以防止并发.这种借助数据库锁机制