多线程的安全问题:

    当多个线程访问共享数据时,可能会出现线程安全问题。

产生问题的原因:

    1.线程任务中有处理到共享的数据;

    2.线程任务中有多条对共享数据的操作。

    一个线程在操作共享数据的过程中,其他线程参与了运算,造成了数据的错误。


如何解决多线程的安全问题:

    只要保证多条操作共享数据的代码在某一时间段,被一条线程所执行,在期间不允许其他线程参与运算。


如何保证?

    1.使用同步代码块

        synchronized(锁){

                需要被同步的代码

        }    

注意:锁可以是任意对象,锁是唯一的。

同步在目前情况下保证了一次只能有一个线程在执行,其他的线程进不来。

同步代码块规则:

    当线程进入同步代码块的时候,先看一下有没有锁,如果有锁,就进入同步代码块中执行代码。进去的同时会获取这把锁,当代码执行完毕,出同步代码块时,将这把锁释放。如果没锁,线程在同步代码块前等待,有锁才进入。


好处:解决了多线程的安全问题。

弊端:降低了效率。

    

    2.同步方法(作用和同步代码块相同)

    也使用synchronized关键字,关键字声明在方法上。

    3.静态方法(和上面两种方法作用相同)

        静态方法同样有锁,不过和成员方法不同,由于静态方法加载的时候还没有对象,所以静态方法的锁用的是该类的字节码文件对象:类名.class。

    

Lock接口

    JDK1.5后出现。

    他比synchronized有更多的操作。

    lock();获取锁

    unlock();释放锁

    为了保证锁一定会被释放,可以使用finally。



线程的死锁

    前提:

    1.必须要有同步锁的嵌套

    2.锁对象要唯一(两把锁都要保证唯一)

public class Test {  
        public static void main(String[] args) {  
            DeadLock deadLock = new DeadLock();  
            Thread t1 = new Thread(deadLock);  
            Thread t2 = new Thread(deadLock);  
            t1.start();  
            t2.start();  
        }  
    }  
      
    // 实现Runnable接口  
    class DeadLock implements Runnable{  
        // 标记,控制线程进程进入不同方法  
        private boolean flag = false;  
        @Override  
        public void run() {  
            // 防止线程正常运行,多试几次,直到出现死锁  
            while(true) {  
                if (!flag) {  
                    synchronized(LockA.LOCK_A) {  
                        System.out.println("我是if的A锁");  
                        synchronized (LockB.LOCK_B) {  
                            System.out.println("我是if的B锁");  
                        }  
                    }  
                      
                } else {  
                    synchronized(LockB.LOCK_B) {  
                        System.out.println("我是else的B锁");  
                        synchronized (LockA.LOCK_A) {  
                            System.out.println("我是else的A锁");  
                        }  
                    }  
                      
                }  
                flag = !flag;  
            }  
        }  
          
    }  
      
    // 继承ReentrantLock类,定义静态常量锁  
    class LockA extends ReentrantLock {  
        private LockA() {  
        }  
        public static final LockA LOCK_A = new LockA();  
    }  
      
    class LockB extends ReentrantLock {  
        private LockB() {  
        }  
        public static final LockB LOCK_B = new LockB();  
    }

程的停止:

    stop()方法    已经过时,不推荐使用。

    interrupt()方法    中断线程

        interrupt方法的作用:

线程中有wait(),sleep()等方法,这时会抛出一个InterruptException异常,并且清楚中断。

       2.调用interrupt方法时,线程中没有上述方法,这时会设置(改变)中断状态的值(true---false)。

public class Test {  
        public static void main(String[] args) throws InterruptedException {  
            TestRunnable runnable = new TestRunnable();  
            Thread t1 = new Thread(runnable);  
            t1.start();  
            t1.interrupt();  
        }  
    }  
      
    class TestRunnable implements Runnable {  
      
        @Override  
        public void run() {                
            while (!Thread.interrupted()) {  
                System.out.println("我是子线程" + ".......run");  
            }  
        }  
          
    }

标记法


    声明一个标识,用来停止线程

public class Test {  
        public static void main(String[] args) throws InterruptedException {  
            TestRunnable runnable = new TestRunnable();  
            Thread t1 = new Thread(runnable);  
            t1.start();  
            Thread.currentThread().sleep(3000);  
            runnable.flag = true;  
        }  
    }  
      
    class TestRunnable implements Runnable {  
        // 声明一个标记,用来控制线程  
        public boolean flag = false;  
        @Override  
        public void run() {  
            while (!flag) {  
                System.out.println("我是子线程" + ".......run");  
            }  
        }  
          
    }