Java 线程同步

1 什么是Java 线程同步

Java中的同步是控制多个线程对任何共享资源的访问的能力。

Java同步是更好的选择,我们希望只允许一个线程访问共享资源。

2 为什么使用Java线程同步

Java线程同步主要用于:

  • 为了防止线程干扰。
  • 保证数据一致性。

3 Java同步类型

同步有两种类型

  • 进程同步
  • 线程同步

本章节,我们将只讨论线程同步

4 Java线程同步的类型

线程同步有互斥和线程间通信两种类型。

  1. 互斥
    • 同步方法。
    • 同步块代码。
    • 静态同步方法。
  2. 线程间通信

5 线程互斥

互斥互助有助于防止线程在共享数据时相互干扰。这可以通过Java中的三种方式完成:

  1. 通过同步方法
  2. 通过同步代码块
  3. 通过静态同步方法

6 Java锁的概念

同步是围绕称为锁或监视器的内部实体构建的。每个对象都有与之关联的锁。按照惯例,需要对对象的字段进行一致访问的线程必须在访问对象之前获取对象的锁,然后在完成对它们的锁定后释放该锁。

从Java 5开始,java.util.concurrent.locks包下面包含几个锁实现。

7 线程并发问题引发数据不一致

在此示例中,没有使用线程同步,会出现输出不一致的情况。让我们来看一个例子:

package com.yiidian;

/**
 * 一点教程网: http://www.yiidian.com
 */
/**
 *  线程并发问题引发数据不一致
 */
class Table{
    void printTable(int n){//method not synchronized
        for(int i=1;i<=5;i++){
            System.out.println(n*i);
            try{
                Thread.sleep(400);
            }catch(Exception e){System.out.println(e);}
        }

    }
}

class MyThread1 extends Thread{
    Table t;
    MyThread1(Table t){
        this.t=t;
    }
    public void run(){
        t.printTable(5);
    }

}
class MyThread2 extends Thread{
    Table t;
    MyThread2(Table t){
        this.t=t;
    }
    public void run(){
        t.printTable(100);
    }
}

class Demo{
    public static void main(String args[]){
        Table obj = new Table();//only one object
        MyThread1 t1=new MyThread1(obj);
        MyThread2 t2=new MyThread2(obj);
        t1.start();
        t2.start();
    }
}

输出结果为:

5
100
10
200
15
300
20
400
25
500

8 Java synchronized方法的例子1

如果将任何方法声明为synchronized方法,则称为同步方法

同步方法用于锁定任何共享资源的对象。

当线程调用同步方法时,它将自动获取该对象的锁,并在线程完成其任务时释放该锁。

package com.yiidian;

/**
 * 一点教程网: http://www.yiidian.com
 */
/**
 *   Java线程同步方法的例子
 */
class Table{
    synchronized void printTable(int n){//synchronized method
        for(int i=1;i<=5;i++){
            System.out.println(n*i);
            try{
                Thread.sleep(400);
            }catch(Exception e){System.out.println(e);}
        }

    }
}

class MyThread1 extends Thread{
    Table t;
    MyThread1(Table t){
        this.t=t;
    }
    public void run(){
        t.printTable(5);
    }

}
class MyThread2 extends Thread{
    Table t;
    MyThread2(Table t){
        this.t=t;
    }
    public void run(){
        t.printTable(100);
    }
}

public class Demo{
    public static void main(String args[]){
        Table obj = new Table();//only one object
        MyThread1 t1=new MyThread1(obj);
        MyThread2 t2=new MyThread2(obj);
        t1.start();
        t2.start();
    }
}

输出结果为:

5
10
15
20
25
100
200
300
400
500

9 Java synchronized方法的例子2

在此程序中,我们通过匿名类创建了两个线程,因此所需的编码更少。

package com.yiidian;

/**
 * 一点教程网: http://www.yiidian.com
 */
/**
 *   Java线程同步方法的例子
 */
//Program of synchronized method by using annonymous class
class Table{
    synchronized void printTable(int n){//synchronized method
        for(int i=1;i<=5;i++){
            System.out.println(n*i);
            try{
                Thread.sleep(400);
            }catch(Exception e){System.out.println(e);}
        }

    }
}

public class Demo{
    public static void main(String args[]){
        final Table obj = new Table();//only one object

        Thread t1=new Thread(){
            public void run(){
                obj.printTable(5);
            }
        };
        Thread t2=new Thread(){
            public void run(){
                obj.printTable(100);
            }
        };

        t1.start();
        t2.start();
    }
}

输出结果为:

100
200
300
400
500
5
10
15
20
25

 

推荐好课