Java多线程和线程同步

2020-11-09  本文已影响0人  如愿以偿丶

1.进程和线程

 1.1.进程和线程

  1.操作系统中运行多个软件
  2.一个运行中的软件可能包含多个进程
  3.一个运行中的进程可能包含多个线程

 1.2.CPU线程和操作系统线程

  1.2.1.CPU线程
    1.多核CPU的每个核各自对立运行,因此每个核一个线程
    2.「四核⼋线程」:CPU硬件方在硬件级别对CPU进行了一核多线程的支持(本质上依然是每个核一个线程)

  1.2.2.操作系统线程
    1.操作系统利用时间分片的方式,把CPU的运行拆分给多条运行逻辑,即为操作系统的线程。

2.线程使用

 2.1.Thread和Runnable
  //Thread
  Thread thread = new Thread(){
        @Override
        public void run() {
            Log.e("TAG","Thrad started------Thread");
       }
    };
  thread.start();
     
 //Runnable
 Runnable runnable = new Runnable() {
       @Override
       public void run() {
           Log.e("TAG","Thrad started------Runnable");
       }
   };
   Thread thread1 = new Thread(runnable);
   thread1.start();
 2.2.Executor 和线程池

  常用:newCachedThreadPool()

//Executor
 Runnable runnable = new Runnable() {
    @Override
    public void run() {
         Log.e("TAG","runnable----------------------");
    }
  };
    Executor executor = Executors.newCachedThreadPool();
    executor.execute(runnable);
    executor.execute(runnable);
    executor.execute(runnable);       

3.线程同步与线程安全

 3.1.synchronized方法
private synchronized void count(int newValue) {
   x = newValue;
   y = newValue;
   if (x != y) {
       System.out.println("x: " + x + ", y:" + y);
   }
 }

问题:
  当我们两个线程同时调用count方法,如果不添加synchronized关键字,会出现x!=y的情况。
因为当线程1执行到count方法的x=newValue,突然切换时间片切换到线程2执行到y = newValue,此时x就会不等于y,此时就会出现数据问题,数据不同步问题。

解决:
  添加synchronized关键字后,会把count方法作为一个整体,当线程1的count方法未执行行完成,此时其他线程执行count方法,此时线程1还持有锁,线程2只能等待线程1执行完成后才能执行count方法。保证数据同步问题。

 3.2.synchronized代码块
private  void count(int newValue) {
  synchronized(this){
     x = newValue;
     y = newValue;
     if (x != y) {
         System.out.println("x: " + x + ", y:" + y);
     }
    }
 }

synchronized关键字的本质:
  1.保证方法内部或代码块内部资源(数据)的互斥访问,即同一时间,由同一个Monitor(可认为是synchronized关键字)监视的代码,最多只能有一个线程在访问。
  2.保证线程之间对监视资源的数据同步,即,任何线程在获取到Monitor后的第一时间,会先将共享内存中的数据复制到自己的缓存中,任何线程在释放Monitor的第一时间会先将缓存中的数据复制到共享内存中。

volatile关键字
  1.保证加了volatile关键字的字段的操作具有原子性和同步性,其中原子性相当于实现了针对单一字段的线程间互斥访问,因此volatile可以看做是简化版的synchronized
  2.volatile关键字只对基本类型(byte,short,int,long,char,float,double,boolean)的赋值操作和对象的引用赋值操作有效。

4.总结

 4.1.线程安全问题的本质:

  在多个线程访问共同的资源时,在某一个线程对资源进行写操作的中途(写入已经开始,但还没结束),其他线程对这个写了一半的资源进行了读操作,或者基于这个写了一半的资源进行了写操作,导致数据出现错误。

 4.2.锁机制的本质:

  1.通过对共享资源进行访问限制,让同一时间只有一个线程可以访问资源,保证了数据的准确性。
  2.不论是线程安全问题,还是针对线程安全问题所衍生出的锁机制,他们的核心都是在共享的资源,而不是在某个方法或者某几行代码。

上一篇下一篇

猜你喜欢

热点阅读