黑马程序员——7 多线程进阶(一)
多线程与CPU和内存的关系
这个回答我认为是很好的比喻了.
CPU对进程操作时不是同时进行,我们知道windows操作系统里面有许多的进程,而CPU是一个一个的来操作这些进程的,当然,多核CPU就可以实现同时操作这些进程,所以为什么CPU核数越多电脑速度越快就是这样,但是内存是一个瓶颈,不能超过这个内存数.
根据上面说的CPU是一个一个的来控制着进程的(高速切换),那么就会出现一个问题,如果我们启动多个线程控制着一个进程里面的数据时,因为CPU是一个一个的处理,而线程可以实现并发,万一要是CPU刚好处理到这里以后跳到其他进程处理时,启动的线程又在处理这个进程的数据,那么就会出现安全隐患,比如:
2个线程控制一个进程的数据
其中一个线程1执行这个进程的数据时CPU刚好切换,线程1被挂起.
这时如果线程2获得CPU执行权时,线程2就执行这个进程的数据,执行完线程1被激活执行数据.
int x = 1;
String name;
int Money;
void run()
{
if(x > 0)//线程1判断完符合条件被挂起,线程2进入判断符合条件
{
x = x - 1;
name = “kvieta丶心灵”;
Money += 1000;
//银行核心代码
……
}
}
根据以上代码结合文字说明,那么我的账户上面岂不是有了2000块钱了!赚了…
解决办法:java中提供一个关键字synchronized,它包括两种用法:synchronized 方法和 synchronized 块
详情可以参阅API.
同步函数中控制线程的进出用this,同步的静态函数中控制线程的进出用该函数所属的类对应的字节码文件.
线程的安全问题:
1、导致安全问题的出现的原因:
当多条语句在操作同一线程共享数据时,一个线程对多条语句只执行了一部分,还没用执行完,另一个线程参与进来执行。导致共享数据的错误。
简单的说就两点:
a、多个线程访问出现延迟。
b、线程随机性 。
注:线程安全问题在理想状态下,不容易出现,但一旦出现对软件的影响是非常大的。
2、解决办法——同步
对多条操作共享数据的语句,只能让一个线程都执行完。在执行过程中,其他线程不可以参与执行。
在java中对于多线程的安全问题提供了专业的解决方式——synchronized(同步)
这里也有两种解决方式,一种是同步代码块,还有就是同步函数。都是利用关键字synchronized来实现。
a、同步代码块
用法:
synchronized(对象)
{需要被同步的代码}
同步可以解决安全问题的根本原因就在那个对象上。其中对象如同锁。持有锁的线程可以在同步中执行。没有持有锁的线程即使获取cpu的执行权,也进不去,因为没有获取锁。
b、同步函数
格式:
在函数上加上synchronized修饰符即可。
那么同步函数用的是哪一个锁呢?
函数需要被对象调用。那么函数都有一个所属对象引用。就是this。所以同步函数使用的锁是this。
3、同步的前提
a,必须要有两个或者两个以上的线程。
b,必须是多个线程使用同一个锁。
4、同步的利弊
好处:解决了多线程的安全问题。
弊端:多个线程需要判断锁,较为消耗资源。
5、如何寻找多线程中的安全问题
a,明确哪些代码是多线程运行代码。
b,明确共享数据。
c,明确多线程运行代码中哪些语句是操作共享数据的。