线程基础—线程的同步
来源:互联网 发布:服装零售软件 编辑:程序博客网 时间:2024/05/23 13:16
线程的同步,首先要了解一下线程的生命周期。
jdk中用Thread.State枚举来表示线程的几种状态。要想实现多线程,必须在主线程中创建新的线程对象。Java语言使用Thread类及其子类的对象来表示线程,在它的一个完整的生命周期中通常要经历如下的五种状态:
1.新建:当一个Thread类或其子类的对象被声明并创建时,新生的线程对象处于新建状态;
2.就绪:处于新建状态的线程被start()后,将进入线程队列等待CPU时间片,此时它已具备了运行的条件;
3.运行:当就绪的线程被调度并获得处理器资源时,便进入运行状态,run()方法定义了线程的操作和功能;
4.阻塞:在某种特殊情况下,被人为挂起或执行输入输出操作时,让出CPU并临时中止自己的执行,进入阻塞状态;
5.死亡:线程完成了它的全部工作或线程被提前强制性地中止。
线程在运行阶段,如果多个线程有共享资源,就会很容易产生同步问题。例如窗口出售车票,如果按照下面线程和客户端写法:
<span style="font-family:KaiTi_GB2312;font-size:18px;">class Window1 implements Runnable{int ticket = 100;public void run(){while(true){if(ticket > 0){System.out.println(Thread.currentThread().getName()+"售出票号是:"+ ticket--);}else{break;}}}}</span>
<span style="font-family:KaiTi_GB2312;font-size:18px;">public class TestWindow1 {public static void main(String[] args){Window1 w = new Window1();Thread t1 =new Thread(w);Thread t2 =new Thread(w);Thread t3 =new Thread(w);t1.setName("线程1");t2.setName("线程2");t3.setName("线程3");t1.start();t2.start();t3.start();}}</span>
通过结果可以看出,100号的车票被两个窗口售出肯定是不符合逻辑的。这就出现了线程安全的问题。
问题的原因 :当多条语句在操作同一个线程共享数据时,一个线程对多条语句只执行了一部分,还没有执行完,另一个线程参与进来执行,导致共享数据的错误。也就是线程1在准备打印车票时此时还未ticket--,而cpu交给了线程2,线程2执行完打印车票打印出100后交给了线程1继续执行,就产生上面这个问题。
java中实现线程的安全,通过通过对多条操作共享数据的语句,只能让一个线程都执行完,在执行过程中,其他线程不可以参与执行。java中实现线程的安全同步机制主要有两种:
1.同步代码块
<span style="font-family:KaiTi_GB2312;font-size:18px;">synchronized(同步监视器){需要被同步的代码块(即为操作共享数据)}</span>上面的代码我们可以更改为:
class Window2 implements Runnable{int ticket = 100; public void run(){while(true){//synchronized(obj){synchronized(this){ // this在这里充当锁if(ticket > 0){try {Thread.currentThread().sleep(10);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}System.out.println(Thread.currentThread().getName()+"票号为Ϊ:"+ ticket--);}}}}}
2.同步方法
synchronized可以放在方法声明中,表示整个方法为同步方法。例如:
public synchronized void show(String name){ ....}
因此上面的方法我们还可以改为:
class Window4 implements Runnable {int ticket = 100; public void run() {while (true) {show();}}public synchronized void show() {if (ticket > 0) {try {Thread.currentThread().sleep(10);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}System.out.println(Thread.currentThread().getName() + "售出车票:" + ticket--);}}}
这里的共享数据就是多个线程共同操作的同一个数据(变量)
同步监视器是由一个类的对象来充当。哪个线程获取此监视器,谁就执synchronized()方法中被同步的代码,俗称锁。在线程同步中所有的线程必须共用同一把锁,在实现的方式中,考虑同步的话,使用this来充当所,但是在继承的方式中要慎用this。
- 线程基础—线程的同步
- LINUX 线程基础, 线程同步,线程控制
- windows线程同步 基础
- 线程基础--同步机制
- 线程同步基础读书笔记
- java基础:线程同步
- java基础--线程同步
- 线程同步基础
- 线程同步基础
- 线程同步基础(一)
- 线程同步基础(二)
- java基础之多线程的安全问题、同步
- 【Java基础】——之线程同步
- Java基础——线程同步通信
- javaSE基础编程——线程同步
- Java基础——线程同步
- 线程同步——用户模式下的线程同步
- Windows线程同步—用户模式下的线程同步
- Composer 在 PHP 5.6 下不能获取数据的解决方法
- Oracle学习(7):集合运算
- ITOO高校云平台V3.1--项目总结(二)
- Android TextView里直接显示图片的三种方法
- VS2010 C++ MFC框架学习笔记3 - 控件Tab顺序设置及模态对话框
- 线程基础—线程的同步
- SlidingMenu和Fragment的总结
- U3d刚体,碰撞,触发器
- Hadoop学习笔记(三)---hadoop的安装
- 右键添加打开终端
- Layered Architecture--分层体系结构
- 在ubuntu14.10上安装theano并且使用GPU加速
- 扩展欧几里得a*y-b*y=1
- Apriori算法简介