Java多线程编程(2)

3、线程同步

线程冲突

当在不同线程中运行作用于相同数据的两个操作时,就会发生干扰。这意味着这两个操作由多个步骤组成,并且步骤顺序重叠。 1.    检索的当前值c。

2.    将检索到的值增加1。

3.    将增加的值存储回c。

public class ThreadConflict implements  Runnable{
    public static int ticket = 100;
    @Override
    public void run() {
        while (ticket > 0) {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() 
	+ "卖了1张票,剩余" + --ticket+"张票");
        }
    }

    public static void main(String[] args) {
        ThreadConflict threadConflict = new ThreadConflict();
        Thread thread1 = new Thread(threadConflict, "售票员1");
        thread1.start();
        Thread thread2 = new Thread(threadConflict, "售票员2");
        thread2.start();
        Thread thread3 = new Thread(threadConflict, "售票员3");
        thread3.start();
    }
}

同步语句

Java编程语言提供了两种基本的同步习惯用法:同步语句(synchronized statements )和同步方法(synchronized methods )。 创建同步代码的一种方法是使用同步语句。与同步方法不同,同步语句必须指定提供内部锁的对象。 同步语句对于通过细粒度同步提高并发性很有用。

public class SynchronizedStatements implements Runnable {
    public static int ticket = 100;
    @Override
    public void run() {
        while (ticket > 0) {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            synchronized ("") {
                if (ticket <= 0) {
                    return;
                }
                System.out.println(Thread.currentThread().getName() 
		+ "卖了1张票,剩余" + --ticket + "张票");
            }
        }
    }
public static void main(String[] args) {
        SynchronizedStatements synchronizedStatements 
		= new SynchronizedStatements();
        Thread thread1 = new Thread(synchronizedStatements, "售票员1");
        thread1.start();
        Thread thread2 = new Thread(synchronizedStatements, "售票员2");
        thread2.start();
        Thread thread3 = new Thread(synchronizedStatements, "售票员3");
        thread3.start();
    }
}

同步方法

要使同步方法,只需将synchronized关键字添加到其声明中。 同步方法提供了一种防止线程干扰和内存一致性错误的简单策略:如果一个对象对一个以上线程可见,则对该对象变量的所有读取或写入均通过synchronized方法完成。

public class SynchronizedMethods implements Runnable {
    public static int ticket = 100;

    @Override
    public void run() {
        sellTicket();
    }

    public synchronized void sellTicket() {
        while (ticket > 0) {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() 
	+ "卖了1张票,剩余" + --ticket + "张票");
        }
    }
public static void main(String[] args) {
        SynchronizedMethods synchronizedMethods 
		= new SynchronizedMethods();
        Thread thread1 = new Thread(synchronizedMethods, "售票员1");
        thread1.start();
        Thread thread2 = new Thread(synchronizedMethods, "售票员2");
        thread2.start();
        Thread thread3 = new Thread(synchronizedMethods, "售票员3");
        thread3.start();
    }
}

4、线程死锁

死锁是一种特定的程序状态,在实体之间,由于循环依赖导致彼此一直处于等待之中,没有任何个体可以继续前进。 死锁不仅仅在线程之间会发生,存在资源独占的进程之间同样也可能出现死锁。通常来说,我们大多是聚焦在多线程场景中的死锁,指两个或多个线程之间,由于互相持有对方需要的锁,互相等待,而永久处于阻塞状态。

public class ThreadDeadLock {

    public static void main(String[] args) {
        DeadLockA deadLockA = new DeadLockA();
        Thread threadA = new Thread(deadLockA, "线程1");
        DeadLockB deadLockB = new DeadLockB();
        Thread threadB = new Thread(deadLockB, "线程2");
        threadA.start();
        threadB.start();
    }
}
class DeadLockA implements Runnable {
    @Override
    public void run() {
        synchronized ("A") {
            System.out.println(Thread.currentThread().getName() 
		+ "持有了A锁,等待B锁。。。");
            synchronized ("B") {
                System.out.println(Thread.currentThread().getName() 
		+ "持有了A锁和B锁");
            }
        }
    }
}
class DeadLockB implements Runnable {
    @Override
    public void run() {
        synchronized ("B") {
            System.out.println(Thread.currentThread().getName() 
		+ "持有了B锁,等待A锁。。。");
            synchronized ("A") {
                System.out.println(Thread.currentThread().getName() 
		+ "持有了B锁和A锁");
            }
        }
    }
}

 

你可能感兴趣的:(Java多线程编程(2))