我们都知道程序是由上至下执行的,在执行当中是由主线程在解析运行。那么现在,如果在其中业务当中我们生成了一个新的线程并让它去执行属于自己的任务,然后在两个线程运行的途中,他们都需要去更改同一个object的属性,那么这时候就有可能会触发线程安全。
什么叫线程不安全?
即两个线程或多个线程,在更改同一个object 时有可能出现脏数据的行为。就是线程不安全。
那么,我们怎么在程序运行的时候保证线程安全呢?
分析问题,想出思路。我们说线程不安全的情况在于多个线程在同一时间,操作同一个对象,可能出现脏数据的情况。那么,我们想在同一时间这个问题。 如果能让该对象在同一时间保证只有一个线程在运行他,是不是就解决了这个问题。
java 提供了synchronized 关键字 用于在同一时间只能是一个线程在解析运行该代码段,也就是同步。
java的内置锁:每个java对象都可以用做一个实现同步的锁,这些锁成为内置锁。线程进入同步代码块或方法的时候会自动获得该锁,在退出同步代码块或方法时会释放该锁。获得内置锁的唯一途径就是进入这个锁的保护的同步代码块或方法。
synchronized 用户修饰方法和代码块
修饰方法:同一时间只能有一个线程在运行该方法。(修饰后,在线程运行的时候会对该方法加锁,也就是内置锁,在这时其它运行到该方法的线程都会被阻塞,当方法运行完成后才会解锁。)
修饰代码块:同一时间只能有一个线程在运行该代码块。
package demo;
public class Demo implements Runnable
{
private OperDemo oper;
public Demo(OperDemo oper)
{
this.oper = oper;
}
@Override
public void run()
{
while(true)
{
if(this.oper.forInt < 10000)
{
this.oper.setIncForInt();
}else{
return;
}
}
}
}
package demo;
public class OperDemo
{
public int forInt = 0;
public synchronized void setIncForInt()
{
this.forInt++;
System.out.println( Thread.currentThread().getName() + " forInt : " + forInt);
}
}
package demo;
public class Index
{
public static void main(String[] args)
{
OperDemo operDemo = new OperDemo();
Demo demo1 = new Demo(operDemo);
Demo demo2 = new Demo(operDemo);
Thread thread_demo1 = new Thread(demo1,"thread_demo1");
Thread thread_demo2 = new Thread(demo2,"thread_demo2");
thread_demo1.start();
thread_demo2.start();
}
}
结果如下
…….
hread_demo1 forInt : 9994
thread_demo1 forInt : 9995
thread_demo1 forInt : 9996
thread_demo1 forInt : 9997
thread_demo1 forInt : 9998
thread_demo1 forInt : 9999
thread_demo1 forInt : 10000
thread_demo2 forInt : 10001
然后我们会看到判定条件是<10000 为什么执行到了10001呢, 那是当forInt = 9999 时,两个线程工作的时候同时判定到了 forInt<10000 解析就是 9999<10000 这个条件成立了。然后先是由thread_demo1 运行,运行时,该方法被加锁(即是阻塞)thread_demo2 不能调用,当thread_demo1 运行完毕后解锁后,thread_demo2 才调用了。