线程三、锁与同步
来源:互联网 发布:jsp导出数据到excel 编辑:程序博客网 时间:2024/05/15 10:54
锁:
是解决资源竞争的基础,为什么说他是基础?
答案:让程序执行达到需求,换句话说就是让程序正确的执行。专业点就是保证线程的安全
在java中,每一个对象都有一把锁,
<span style="font-size:18px;">package test;//test的每一个实例都有一把锁public class test {public int x = 0;//synchronized关键字意图:获取this的对象锁//synchronized的范围:函数public synchronized void do1(){this.x++; }public void do2(){//synchronized关键字意图:获取参数this的对象锁//synchronized的范围:synchronized子句synchronized(this){this.x++; }}}</span>
那么锁有什么用呢?只有它才能保证多线程程序的正确
例子:有一个变量x=0,我们用两个线程对x连续+1 10000次,要求x最后的结果为20000
我们看一个不正确的程序,然后我们用锁让程序正确
错的程序:
<span style="font-size:18px;">public class test implements Runnable{public static int x=0;public void do1(){for(int i =0;i<10000;i++) x = x+1;}public void run() {do1();}public static void main(String[] args) {Thread t1 = new Thread(new test());Thread t2 = new Thread(new test());t1.start();t2.start();try { //主线程睡一会,等待t1,t2执行完毕后再执行Thread.sleep(5000);} catch (InterruptedException e) {e.printStackTrace();}System.out.print(test.x);}}</span>
这个程序执行完后,结果很难=20000,并且每次运行结果都不一致,
正确的程序:
<span style="font-size:18px;">public class test implements Runnable{public static Object obj = new Object();public static int x=0;public void do1(){//获取obj的锁synchronized(obj){for(int i =0;i<10000;i++) x = x+1;}}public void run() {do1();}public static void main(String[] args) {Thread t1 = new Thread(new test());Thread t2 = new Thread(new test());t1.start();t2.start();try { //主线程睡一会,等待t1,t2执行完毕后再执行Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.print(test.x);}}</span>
每次运行结果:20000
为什么要用锁,目的就是在多线程环境下,保证运行的正确性,让程序的运行不乱套,保证安全的运行。
当多个线程执行的时候,每个线程都会有自己独立的堆栈空间,对一个共享变量问题就来了,什么问题呢?
1、第一个线程用到共享变量时(进栈),内存中的变量被放入处理器数据寄存器中,假如x=0,此时x不断+1,但是结果并没有马上返回共享变量所在的内存空间,也就是说,共享变量的值此时还是0,什么时候返回计算结果给内存,这个要看处理器的是如何设计的了(工作原理了,优先算法 呵呵)....
2、第二个线程和第一个线程一样的执行过程,他也会从内存中拿x放入数据寄存器,他取到的x的初值可能也是0,而取不到第一个线程寄存器中的结果
可想而知,乱了
如何解决:
锁,如果给这个共享变量加锁,通过锁的方式访问变量呢?
锁能保证第一个线程(准确的说是当前线程)把执行结果返回内存后,才会解锁,继续让第一个线程或者第二个线程竞争上岗(获取锁),上岗(获取了锁)的线程继续访问共享变量。
这样就能保证每一次只有一个线程访问变量,并返回结果给内存,做到了同步,从而保证了线程安全。
所以,锁是线程编程的第一课,他是保证线程安全性的前提。
- 线程三、锁与同步
- Java线程(三):同步与锁
- 线程与同步之三——读写锁
- 多线程学习(三)线程的同步与锁
- 线程,同步与锁
- 线程同步与锁
- 线程同步与锁
- 线程同步与锁
- 线程同步三:Slim锁
- 三线程的互斥与同步
- MFC多线程与线程同步 (三)
- Android---手动创建线程与GUI线程同步(三)
- 线程的同步与锁
- 线程的同步与锁
- 线程的同步与锁
- java 线程 同步与锁
- Java线程同步与锁
- iOS 线程同步与锁
- spring封装的jdbc template方法 概览
- IP 地址转换 inet_addr() inet_ntoa() 笔记
- create_function 创建匿名函数
- maven dependency scop 解决maven和tomcat包冲突
- ORACLE not available
- 线程三、锁与同步
- <黑马程序员>RandomAccessFile类的使用简述
- 100行代码实现最简单的基于FFMPEG+SDL的视频播放器
- poj2531Network Saboteur
- jsonccp的简单使用
- 分平面问题
- iPhone:苹果开发网络编程知识总结 使用NSConnection下载数据
- 经纬财富:娄底黄金多头如期上涨 加速度只差临门一脚
- JavaWeb学习笔记 第十一记