Summer7C

首先是一段代码:

 1 public class HasSelfPrivateNum {
 2     public void addI(String username){
 3         try {
 4             int num=0;
 5             if(username.equals("a")){
 6                 num=100;
 7                 System.out.println("a set over! ");
 8                 Thread.sleep(2000);
 9             }else{
10                 num=200;
11                 System.out.println("b set over! ");
12             }
13             System.out.println(username+" num="+num);
14         } catch (InterruptedException e) {
15             e.printStackTrace();
16         }
17     }
18 }

上述代码中的含义是HasSelfPrivateNum对象的A和B的判断

之后有两个线程:

 1 public class ThreadA extends Thread {
 2     private HasSelfPrivateNum numRef;
 3     public ThreadA(HasSelfPrivateNum numRef){
 4         super();
 5         this.numRef=numRef;
 6     }
 7 
 8     public void run(){
 9         super.run();
10         numRef.addI("a");
11     }
12 }
 1 public class ThreadB extends Thread{
 2     private HasSelfPrivateNum numRef;
 3     public ThreadB(HasSelfPrivateNum numRef){
 4         super();
 5         this.numRef=numRef;
 6     }
 7 
 8     public void run(){
 9         super.run();
10         numRef.addI("b");
11     }
12 }

我们可以看出来线程A和线程B中我们创建了HasSelfPrivateNum实例。

运行结果中可以看出来,这个程序不存在非线程安全性问题,为什么呢,因为这个变量是方法内部的,方法内部的变量是私有的特性造成了线程安全,并且这个其本身永远线程安全。接下来吧int num这一行代码放在方法之外我们会看到什么呢?

这时我们会看到线程不安全了,两个对象同时操作了业务中的实例变量,所以发生了线程不安全的问题,原因是没有同步,为了让线程安全我们可以家一个同步锁来解决这个问题:

加了同步锁之后运行就安全了,直到A线程执行完成之后在会执行B线程,如果一个线程没有执行完毕,那么其他线程就无法访问这个线程。和之前那个同步锁的道理是一样的,这就是线程的同步.

以上就是线程同步的道理;

下面是线程的异步:

在刚才的程序上在修改main方法中的代码为:

 

 

同时创建两个对象然后再两个线程中运行我们会发现运行结果:

我们现在比较一下两个结果:

我们会发现在同步的时候,执行方式为执行A线程直到A线程完全执行完毕之后,再去执行B,原因是因为只有一个Has对象,资源存在竞争关系,当我们使用同步锁的时候就会受到同步机制的影响,当A线程占用了这个对象的资源的时候,其他线程就无法访问这个资源了,直到A执行完毕之后,释放了这个资源,这个时候B线程才有资格去拿到这个线程.我们把这个机制叫做同步.

那个第二个输出方式就和前一个不一样了,这种打印效果就是异步的.两个线程访问了两个不同的对象,这两个不同的对象产生了两个锁,所以一个线程中一个对象的锁并锁不住其他对象,所以就会这样输出.

结论:Java中synhronized关键字锁住的是一个对象,而不是一个方法或者一段代码.

 

=========================================

分类:

技术点:

相关文章: