线程又称之为“轻量级进程”,和进程一样拥有独立的执行控制,由操作系统负责调度。区别在于其没有独立的存储空间,而是和所属进程中的其他线程共享一个存储空间,这使得线程间的通信较进程简单。多线程程序,必须注意每个线程是否干扰了其他线程的工作。
因为每个线程都能读写相同的共享数据,由于数据共享会带来同步问题,进而会导致死锁的产生。由于多线程带来的性能改善是以可靠性为代价的,主要是因为有可能产生线程死锁。死锁是由于多个线程同时被阻塞,一个或者全部线程都在等待某个资源被释放,由于线程被无限期的阻塞,因此程序不能正常运行。简单的说是线程死锁时,第一个线程等待第二个线程释放资源,而同时第二个线程又在等待第一个线程释放资源,
导致死锁的根源是不适当的运用synchronized 关键字来管理线程对特定对象的访问,其作用就是确保某个时刻只是运行一个线程被允许执行特定的代码块,因此被允许执行的线程首先必须拥有对变量或者对象的排他性访问权,当线程访问对象的时候,线程就会给对象枷锁,而这个锁导致其他也要访问同一个对象的线程被阻塞,直至第一个线程释放加载在对象上的锁。
一个Java程序的多线程之间可以共享数据,当线程以异步方式来访问共享数据时,有时是不安全的或者是不合逻辑的,例如同一时刻一个线程在读取数据,另一个线程在处理数据,当处理数据的线程没有等到读取数据的线程读取完毕就处理数据,必然导致错误的处理结果,处理数据的线程不能处理当前还没有读取结束的数据,但是可以读取其他数据。
如果我们采用多线程同步控制机制,那么等到第一个线程读取数据后第2个线程才能处理该数据就会避免错误,可见线程同步是多线程编程当中的一个相当重要的技术。
线程同步是一个我们在处理线程的时候需要注意的问题,同步方法要用synchronized关键字修饰,修饰后,当一个线程使用这个方法后其他线程就需要等待这个方法的使用权,直到该线程完成该方法。
用Java关键字synchronized同步对共享数据操作的方法,在一个对象中用synchronized生命的方法为同步方法,Java中有一个同步模型--监视器负责管理线程对对象中的同步方法的访问,赋予该对象唯一一把钥匙。当多个线程进入对象,只有取得该对象钥匙的线程才可以访问同步方法,其他线程在该对象中等待。直到该线程用wait()方法放弃这把钥匙,其他等待的线程抢占该钥匙,抢占到钥匙的线程才可以执行,而没有取得钥匙的线程仍然被阻塞到该对象中继续等待。
防止死锁,防止错误结果的发生,都需要线程同步机制来协调,利用关键字synchronized
关键字synchronized放置在访问控制权限之后 返回类型之前
感觉Jcretor这个软件的缺陷还是很大的
一个线程同步锁synchronized竟然运行失误
在命令行中运行完全没有问题
public class ThreadSynchronized {
public static void main(String[] args){
//启动两线程
new cls1().start();
new cls2().start();
}
}
//该线程类用来添加数字
class cls1 extends Thread{
com a = new com();
public void run(){
int i=0 ;
//增加数字
while(i<=100) {
a.synchM(this.getClass().getName(),i);
i++;
}
}
}
//该线程类用来减少数字
class cls2 extends Thread{
com b = new com();
public void run(){
int i=100 ;
//减去数字
while(i>0) {
b.synchN(this.getClass().getName(),i);
i--;
}
}
}
class com {
int i=0;
//同步方法
public synchronized void synchM(String obj,int i){
this.i=i;
System.out.println(obj + "访问,"+this.i);
}
public synchronized void synchN(String obj,int j){
this.i=j;
System.out.println(obj + "访问,"+this.i);
}
}
所以当第一个线程将数加到100的时候第二个线程才可以执行数字的减法操作。
线程同步
线程同步的方式和机制: