多线程

多线程-生产者消费者(synchronized同步)

我的未来我决定 提交于 2020-03-12 04:58:46
正解博客:https://blog.csdn.net/u011863767/article/details/59731447 永远在循环(loop)里调用 wait 和 notify,不是在 If 语句 现在你知道wait应该永远在被synchronized的背景下和那个被多线程共享的对象上调用,下一个一定要记住的问题就是,你应该永远在while循环,而不是if语句中调用wait。因为线程是在某些条件下等待的——在我们的例子里,即“如果缓冲区队列是满的话,那么生产者线程应该等待”,你可能直觉就会写一个if语句。但if语句存在一些微妙的小问题,导致即使条件没被满足,你的线程你也有可能被错误地唤醒。所以如果你不在线程被唤醒后再次使用while循环检查唤醒条件是否被满足,你的程序就有可能会出错——例如在缓冲区为满的时候生产者继续生成数据,或者缓冲区为空的时候消费者开始小号数据。所以记住, 永远在while循环而不是if语句中使用wait!我会推荐阅读《 Effective Java 》,这是关于如何正确使用wait和notify的最好的参考资料。 有的这样说:(http://www.tuicool.com/articles/a6ram23) 因为在多核处理器环境中, Signal 唤醒操作可能会激活多于一个线程(阻塞在条件变量上的线程),使得多个调用等待的线程返回

多线程输出

自作多情 提交于 2020-03-12 04:46:55
编写一个可以从 1 到 n 输出代表这个数字的字符串的程序,但是: 如果这个数字可以被 3 整除,输出 "fizz"。 如果这个数字可以被 5 整除,输出 "buzz"。 如果这个数字可以同时被 3 和 5 整除,输出 "fizzbuzz"。 例如,当 n = 15,输出: 1, 2, fizz, 4, buzz, fizz, 7, 8, fizz, buzz, 11, fizz, 13, 14, fizzbuzz。 假设有这么一个类: class FizzBuzz { public FizzBuzz(int n) { … } // constructor public void fizz(printFizz) { … } // only output “fizz” public void buzz(printBuzz) { … } // only output “buzz” public void fizzbuzz(printFizzBuzz) { … } // only output “fizzbuzz” public void number(printNumber) { … } // only output the numbers } 请你实现一个有四个线程的多线程版 FizzBuzz, 同一个 FizzBuzz 实例会被如下四个线程使用: 线程A将调用 fizz()

Java多线程(八)——join()

这一生的挚爱 提交于 2020-03-12 04:01:31
一、join()介绍 join() 定义在Thread.java中。 join() 的作用: 让“主线程”等待“子线程”结束之后才能继续运行。 这句话可能有点晦涩,我们还是通过例子去理解: // 主线程 public class Father extends Thread { public void run() { Son s = new Son(); s.start(); s.join(); ... } } // 子线程 public class Son extends Thread { public void run() { ... } } 说明 : 上面的有两个类Father(主线程类)和Son(子线程类)。因为Son是在Father中创建并启动的,所以,Father是主线程类,Son是子线程类。 在Father主线程中,通过new Son()新建“子线程s”。接着通过s.start()启动“子线程s”,并且调用s.join()。 在调用s.join()之后,Father主线程会一直等待,直到“子线程s”运行完毕;在“子线程s”运行完毕之后,Father主线程才能接着运行。 这也就是我们所说的“join()的作用,是让主线程会等待子线程结束之后才能继续运行”! 二、join()源码分析 public final void join() throws

CountDownLatch 处理多线程问题

狂风中的少年 提交于 2020-03-12 03:57:46
多线程问题记录(自己的理解) // 主线程及 待处理的数据 List < User > users = 业务处理后形成的集合 // CountDownLatch 用来处理多线程等待问题,如 主线程 -> 多线程 -> 等待多线程全部执行完成 -> 主线程 // 初始化计数器 CountDownLatch downLatch = new CountDownLatch ( users . size ( ) ) ; // 开启多线程任务 users . forEach ( user - > { new Thread ( new Runnable ( ) { @Override public void run ( ) { System . out . println ( "当前线程:" +  Thread . currentThread ( ) . getName ( ) ) ; try { // user的业务处理方法 . . . . . . } catch ( Exception e ) { e . printStackTrace ( ) ; } finally { downLatch . countDown ( ) ; // 执行结束后计数器减 1 , 计数器结束后多线程任务结束 // 此方法最好放finally内部, 不然上面user业务代码异常后可能导致 // downLatch

单例模式

大城市里の小女人 提交于 2020-03-11 21:40:44
这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。 注意: 1、单例类只能有一个实例。 2、单例类必须自己创建自己的唯一实例。 3、单例类必须给所有其他对象提供这一实例。 1、懒汉式,线程不安全 是否 Lazy 初始化:是 是否多线程安全:否 实现难度:易 描述:这种方式是最基本的实现方式,这种实现最大的问题就是不支持多线程。因为没有加锁 synchronized,所以严格意义上它并不算单例模式。 这种方式 lazy loading 很明显,不要求线程安全,在多线程不能正常工作。 public class Singleton { private static Singleton instance; private Singleton (){} public static Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; } } 2、懒汉式,线程安全 是否 Lazy 初始化: 是 是否多线程安全: 是 实现难度: 易 描述: 这种方式具备很好的 lazy loading,能够在多线程中很好的工作,但是,效率很低,99% 情况下不需要同步

Linux内核多线程(四)

我怕爱的太早我们不能终老 提交于 2020-03-11 18:59:43
自己创建的内核线程,当把模块加载到内核之后,可以通过:ps –ef 命令来查看线程运行的情况。通过该命令可以看到该线程的pid和ppid等。也可以通过使用kill –s 9 pid 来杀死对应pid的线程。如果要支持kill命令自己创建的线程里面需要能接受kill信号。这里我们就来举一个例,支持kill命令,同时rmmod的时候也能杀死线程。 #include <linux/kernel.h> #include <linux/module.h> #include <linux/init.h> #include <linux/param.h> #include <linux/jiffies.h> #include <asm/system.h> #include <asm/processor.h> #include <asm/signal.h> #include <linux/completion.h> // for DECLARE_COMPLETION() #include <linux/sched.h> #include <linux/delay.h> // mdelay() #include <linux/kthread.h> MODULE_LICENSE("GPL"); static DECLARE_COMPLETION(my_completion); static

多线程什么时候该加锁?

半腔热情 提交于 2020-03-11 17:52:33
1 .加锁、解锁(同步/互斥)是多线程中非常基本的操作,但我却看到不少的代码对它们处理的很不好。简单说来有三类问题,一是加锁范围太大,虽然避免了逻辑错误,但锁了不该锁的东西,难免降低程序的效率;二是该锁的不锁,导致各种莫名其妙的错误;三是加锁方式不合适,该用临界区的用内核对象等,也会降低程序的效率。 要正确的运用锁操作,首先要弄清楚什么时候需要加锁。一般可能“同时发生多个写操作”或“同时发生读写操作”时,必需要加Lock. 2,NET警惕匿名方法造成变量共享 http://www.csharpwin.com/csharpspace/8200r3812.shtml 此类问题也不光会出现在匿名方法中。如果您使用Lambda表达式创建了一个表达式树,其中也用到了一个“局部变量”,那么表达式树在解析或执行时同样也会获取“当前”的值,而不是创建表达式树时的值。 即:Linq中使用List.AsParallel() //账单所包含的订单总重。此时会导致未知的错误!! 可能 同一时间有线程A在返回Weigh(读),另一线程B进行Sum计算;产生多线程同时读写操作。 decimal orderTotalWeight = order7.AsParallel().Sum(m => bllOrderInfo.GetProductCodeWeight(m. Co de) * m.Quantity)

多线程并发问题

核能气质少年 提交于 2020-03-11 13:05:43
多线程: --并发问题 线程对于内存数据的访问会提供一个内存副本供其使用,在线程使用结束时,将副本内容merge到内存中。以下的图就是线程并发的问题。 数据1被线程1和线程2都拿走各拿的都是一个拷贝的副本,这个时候都对数据+1,在结束时副本数据都为2,本来应为3,merge后数据也为2。 voliate 修饰词: 强制从内存中获取,如果有变更则直接更新内存,可以大范围的解决并发冲突,但是不能完全消除掉。 synchronized: 表示将内存给锁住,一次只能有一个线程去取,取完了再下一个,这样保证安全,但是会造成堵塞。 目前java7,8用的较新的有: 1. AtomicInteger 做计数用,内部使用voliate和Unsafe类。 对于UnSafe类,内部修饰符都是native即会调用系统语言操作内存,有指针的引入。其中pack()和unpack()控制线程的挂起还是继续。 CAS ---比较并交换(compare and swap)是一条CPU并发 CAS方法控制对CPU原子指令操作,保证顺序执行并不会被打断实现免疫死锁。 但ABA问题就需要使用AtomicStampedReference类加入时间戳来判断是否内存的数据有没有过改动。 Lock和unLock也就是通过 调用CAS将要锁的对象预期值设为null,使得无法进入cpu处理,然后会在门外排队等候,等到自己又被排除掉

Java多线程系列--利用自旋原理来无锁实现“只创建一次”的场景

自古美人都是妖i 提交于 2020-03-11 10:09:21
相信看过之前几篇自旋锁实现的同学对设计一个自旋锁会有一定的感觉,有几个实现的要点很实用: 1. 使用AtomicBoolean原子变量的getAndSet(true)方法来实现并发情况下,找到第一个成功执行方法的线程。这个技巧经常使用,在并发编程中经常会遇到这种需求 2.经常会使用volatile boolean类型的变量在多个线程之间同步状态,需要注意的是,对volatile变量的修改只具有可见性,不具有原子性(比如++操作)。 3. 使用一个AtomicReference原子变量的getAndSet方法来创建一个虚拟的链表结构,原理也是CAS操作,在队列锁中经常使用 这篇结合一个实例来说说如何灵活地利用这些技巧实现无锁的能力。 在实际开发中会经常遇到“只创建一次”的场景,这里说的“只创建一次”不是说单实例模式。单实例模式也是解决只创建一次的问题,关于单实例模式有很多技巧来实现高并发情况下只创建一个对象的问题,这里不讨论。 单实例模式解决的问题是所有线程都公用一个静态的引用,可以用volatile变量来标示这个静态引用,从而在所有线程之间共享这个静态引用的状态是否已经改变。 这里说的“只创建一次”的场景是这个需要创建一次的对象不是直接被全局的引用所引用,而是间接地被引用。经常有这种情况,全局维护一个并发的ConcurrentMap, Map的每个Key对应一个对象

C++11 原生标准多线程

空扰寡人 提交于 2020-03-11 10:06:20
之所以称之为C++11原生标准多线程,因为在C++中C++11版本才加入的多线程。所谓原生也就是C++语言自带的,区别于其他库实现,比如POSIX,Boost,winAPI,QT【藐视很少有人提到QT的多线程,不过我就是因为要使用QT的多线程库,才认真学习C++11原生标准多线程的。】等的多线程实现。关于系统学习C++原生多线程编程的书,我推荐由Anthony Williams所著的《Cpp Concurrency In Action》,中文版由陈晓伟所译。Anthony Williams是C++11多线程标准起草着之一。 《C++ Concurrency in Action》中文版 在线阅读可以访问陈晓伟的gitbook,他是免费开源的。 关于并发 《C++ Concurrency in Action》一书中对并发通俗的解释: 最简单和最基本的并发,是指两个或更多独立的活动同时发生。 并发在生活中随处可见,我们可以一边走路一边说话,也可以两只手同时作不同的动作,还有我们每个人都过着相互独立的生活——当我在游泳的时候,你可以看球赛,等等。 为什么使用并发 : 《C++ Concurrency in Action》中介绍的有点抽象,有点深奥。通俗的讲,就是 我们希望在相同的时间内做更多的事情: 把关注点(SOS)【我们要做的事情、任务】分离。还有就是 我们希望通过并发提高一下性能