完美的多线程编程方案

这是去年为了找工作,写的一个技术演示:以多线程暴力破解MD5密码为例,来演示一个完美的多线程编程方案。

在十年前,我写过一个单线程的暴力破解MD5密码程序(因为当时CPU还都是单核的),这次是把原来的程序多线程化了。
这个技术演示,写了多个不同实现方式的多个版本,一共花了2天时间(2014年5月3日-2014年5月4日)。

加密密码的暴力破解原理,不是本文重点,这里就不详细介绍了。
简单举例说明一下,对于尝试字符集为 a-z 26个小写字母,尝试长度为8位的话,就是把 a, b, ... z, aa, ab, ... zy, zz, aaa, ... aaaaaaaa, aaaaaaab, ... zzzzzzzy, zzzzzzzz,这26个小写字母,8位长度以内,所有的组合都尝试一遍,所以叫做暴力破解。尝试的结果,如果原加密密码在这个范围内,就必然找到。如果原加密密码不在这个范围内,那么该范围内的所有可能全部尝试完后,没有找到。尝试的方法就是对自己生成的每一个尝试串,进行和加密密码相同加密方式的加密,然后把加密后的尝试串,和加密密码进行比较,相同就说明找到了。

这种暴力破解,需要CPU进行超大量的计算。而需要CPU进行超大量计算的场景,是多线程技术的一个非常重要的应用场景。
我们以实例,来对暴力破解计算量形成一些概念:
以26个小写字母的各种组合进行尝试的话:
试完单独1位,需要对26种尝试串(a-z),进行计算和比较。
试完单独2位,需要对26+26*26=702种尝试串,进行计算和比较。
试完单独8位,需要对26的8次方+26的7次方+...+26=2171.80147158亿种尝试串,进行计算和比较。
使用四核 @3.4GHz 的CPU,以四线程(线程数超过CPU实际核数的话,速度不会提高)跑完2171.8亿种可能的话,估计要4个多小时。而以单线程跑完2171.8亿种可能的话,估计要16个小时以上。
大家有兴趣的话,可以下载本文附带的程序,自己尝试一下。
可以看到在需要CPU进行超大量计算的场景,多线程技术的使用是多么有意义。

多线程共同访问和处理同一数据源,一个非常重要的问题是,访问时需要互斥,否则的话,可能造成遗漏处理数据,或者重复处理数据。少量的重复处理数据是可以接受的,但是遗漏处理数据是不可接受的。为什么会出现重复和遗漏,我们这里不展开讲了。所以,多线程共同访问和处理同一数据源,访问时必需要互斥。

下面我们就来看一下,我所尝试过的几种实现方案。

多线程方案1:
尝试串只有1个。多个线程轮流取,然后再进行计算和比较。
这样的话,各个线程进行尝试的连续性好。但是,当一个线程在生成尝试串的过程中,另几个线程不能访问尝试串,线程需要阻塞等待。预计会经常出现这种情况,会很影响速度。

程序实现,
如果使用mutex来进行线程互斥的话,对速度的影响极为巨大,因为mutex部分代码的执行,四线程版甚至比单线程版还要慢很多很多。("ddzzzz"的md5的破解。四线程使用mutex互斥,118984ms。单线程大约13500ms。四线程比单线程还慢了8倍多)
如果使用InterlockedIncrement64,对程序的限制大。

多线程方案2:
把任务分成大致相等的n份(n为cpu的核数),然后创建n个线程,每个线程完成1份。
没有互斥的问题。

逻辑清晰性差,将来如果用于不同应用场景,代码比较难修改。

未作程序实现。

多线程方案3:
把任务分成固定的份数,然后创建n个线程(n为cpu的核数),每个线程做1份,做完之后,再去领1份,直到将所有的份数全部做完。

线程内,需要完成领一份的代码。领一份部分需要互斥。互斥部分出现的频率很少。

未作程序实现。

多线程方案4:
创建n个线程(n为cpu的核数)。
每个线程每次从总任务中,取一部分的任务进行处理,这部分任务处理完之后,再去取。直到将所有的任务全部处理完。好处是分配的比较均匀。连续性也较好。

程序实现,
"ddzzzz"的md5的破解,3线程4641ms。效果最好。

为什么说多线程方案4,是一种比较完美的多线程编程方案:
1,在一个对执行效率有很高要求的场景下,执行效率很高。
2,代码逻辑性非常好,适用性很广。很少的改动,就可以应用在很多的应用场景中。

本文所附带程序(http://pan.baidu.com/s/1i3ip4nb)说明:
MD5Calc.exe 图形界面,将指定的明文密码转换为MD5加密密码。
JiurlMd5CrackGui.exe 图形界面,多线程暴力破解演示程序,以本文多线程方案4实现。可以自行设定使用的线程数,默认线程数为CPU内核数减1。
TryCharset.txt 指定尝试字符集。
CryptedPassword.txt 指定要破解的密码。

临时主页:http://blog.sina.com.cn/ddqqppb
QQ高大上交流群:91877299

时间: 2024-11-04 14:13:39

完美的多线程编程方案的相关文章

多线程编程1-NSThread

前言 每个iOS应用程序都有个专门用来更新显示UI界面.处理用户触摸事件的主线程,因此不能将其他太耗时的操作放在主线程中执行,不然会造成主线程堵塞(出现卡机现象),带来极坏的用户体验.一般的解决方案就是将那些耗时的操作放到另外一个线程中去执行,多线程编程是防止主线程堵塞,增加运行效率的最佳方法. iOS中有3种常见的多线程编程方法: 1.NSThread 这种方法需要管理线程的生命周期.同步.加锁问题,会导致一定的性能开销 2.NSOperation和NSOperationQueue 是基于OC

多线程编程1

参考资料: http://blog.csdn.net/JXH_123/article/details/23450031                             秒杀多线程系列 http://www.baidu.com/index.php?tn=utf8kb_oem_dg&addresssearch=1#wd=C%2B%2B%E5%BE%AA%E7%8E%AF%E6%B6%88%E6%81%AF%E9%98%9F%E5%88%97&ie=utf-8&tn=utf8kb

Android开发实践:多线程编程小结

我们知道,Android系统为了提高程序的实时响应能力,不允许在UI线程中进行耗时的操作,否则会出现ANR异常,因此必须将耗时的任务放到非UI线程中执行.Android/Java提供了很多类来帮助大家完成异步操作,比如:Thread类,Timer类,AsyncTask类,HandlerThread类,以及Executor接口.这些类都分别在什么场合下使用呢? 本文简单地总结一下Android开发中常见的多线程类型和解决方案,并比较和分析了各个方案的区别,以便更好地理解和应用这些API接口. 1.

iOS中有3种常见的多线程编程方法

1.NSThread 这种方法需要管理线程的生命周期.同步.加锁问题,会导致一定的性能开销 2.NSOperation和NSOperationQueue 是基于OC实现的.NSOperation以面向对象的方式封装了需要执行的操作,然后可以将这个操作放到一个NSOperationQueue中去异步执行.不必关心线程管理.同步等问题. 3.Grand Centeral Dispatch 简称GCD,iOS4才开始支持,是纯C语言的API.自iPad2开始,苹果设备开始有了双核CPU,为了充分利用这

java多线程编程核心技术----心得1

1.线程和进程 进程和线程的例子很多,因为是学习笔记,那就说一种我自己感觉很好理解的,就是我们天天使用的QQ,但我们运行QQ.exe程序时,进程就开始,我们可以同时打开对个聊天窗口,可以多人视频过,甚至可以一边视频一边手动聊天(可能音响坏了吧 ...),其中每一个任务完全可以理解成是“线程”在工作,传音乐,图片表情,传文件等功能都有对应的线程在后台默默运行. 2使用多线程 2.1.1  一个类怎么就能变成“线程”了呢? 在回答上面的问题之前:我们首先要认识一个类和一个借口,Thread类和Run

让Duilib多线程编程更easy

一.Duilib不能开发多线程程序? 记得非常久曾经就听有人说过Duilib的多线程支持性不好,原因是Duilib里面的控件是用数组管理的全局变量,不能进行多线程訪问,加锁非常麻烦.事实上这个说法是非常不合理的,以至于在开发多线程程序时直接将Duilib拒之门外.当然使用Duilib里面开发多线程是木有不论什么问题的,不要单纯地觉得:其它的界面库就能使用多个线程同一时候操作一个控件,Duilib就不行.事实证明,这点MFC做不到,WinForm也做不到,连微软自己都搞不定的东西,不能算Duili

多线程编程4 - GCD

一.简介 在iOS所有实现多线程的方案中,GCD应该是最有魅力的,因为GCD本身是苹果公司为多核的并行运算提出的解决方案.GCD在工作时会自动利用更多的处理器核心,以充分利用更强大的机器.GCD是Grand Central Dispatch的简称,它是基于C语言的.如果使用GCD,完全由系统管理线程,我们不需要编写线程代码.只需定义想要执行的任务,然后添加到适当的调度队列(dispatch queue).GCD会负责创建线程和调度你的任务,系统直接提供线程管理 二.调度队列(dispath qu

[转载] C++ 多线程编程总结

原文: http://www.cnblogs.com/zhiranok/archive/2012/05/13/cpp_multi_thread.html 在开发C++程序时,一般在吞吐量.并发.实时性上有较高的要求.设计C++程序时,总结起来可以从如下几点提高效率: l  并发 l  异步 l  缓存 下面将我平常工作中遇到一些问题例举一二,其设计思想无非以上三点. 1任务队列 1.1    以生产者-消费者模型设计任务队列 生产者-消费者模型是人们非常熟悉的模型,比如在某个服务器程序中,当Us

不再为Core Data多线程编程而头疼

by Saul Mora原文链接:http://www.cimgf.com/2011/05/04/core-data-and-threads-without-the-headache/ 我知道我曾经提到我要写一篇关于定制fetch requests的文章,然而,在我为Active Record Fetching project(现在已经改名为MagicalRecord)编写了一些代码之后,我觉得写一篇关于fetching–threading.的文章更好一些. 当大多数cocoa开发者提到Core