1、为什么需要同步

【示例代码】

  1. public class Constant {
  2. public static int count = 0;
  3. }
  4. public class MethodA {
  5. public void process(){
  6. Constant.count++;
  7. System.out.println(Thread.currentThread().getName()+" - count="+Constant.count);
  8. }
  9. }
  10. public class MyThread01 {
  11. public static void main(String[] args) {
  12. for(int i=0;i<10;i++){
  13. Thread t = new Thread(new Runnable() {
  14. @Override
  15. public void run() {
  16. MethodA methodA = new MethodA();
  17. methodA.process();
  18. }
  19. });
  20. t.start();
  21. }
  22. }
  23. }
  24. --------------
  25. Thread-4 - count=4
  26. Thread-9 - count=10
  27. Thread-6 - count=9
  28. Thread-5 - count=8
  29. Thread-0 - count=7
  30. Thread-1 - count=4
  31. Thread-2 - count=4
  32. Thread-3 - count=6
  33. Thread-7 - count=4
  34. Thread-8 - count=5

【示例代码】

  1. public class MyThread02 {
  2. public static void main(String[] args) {
  3. MethodB methodB = new MethodB();
  4. for(int i=0;i<10;i++){
  5. Thread t = new Thread(new Runnable() {
  6. @Override
  7. public void run() {
  8. methodB.process();
  9. }
  10. });
  11. t.start();
  12. }
  13. }
  14. }
  15. -------------
  16. Thread-5 - count=6
  17. Thread-1 - count=10
  18. Thread-0 - count=6
  19. Thread-8 - count=9
  20. Thread-2 - count=9
  21. Thread-4 - count=7
  22. Thread-3 - count=8
  23. Thread-6 - count=6
  24. Thread-7 - count=6
  25. Thread-9 - count=6

2、使用线程同步

  1. public class MethodA {
  2. public void process(){
  3. synchronized(Constant.class){
  4. Constant.count++;
  5. System.out.println(Thread.currentThread().getName()+" - count="+Constant.count);
  6. }
  7. }
  8. }
  9. public class MyThread01 {
  10. public static void main(String[] args) {
  11. for(int i=0;i<10;i++){
  12. Thread t = new Thread(new Runnable() {
  13. @Override
  14. public void run() {
  15. MethodA methodA = new MethodA();
  16. methodA.process();
  17. }
  18. });
  19. t.start();
  20. }
  21. }
  22. }
  23. --------------
  24. Thread-0 - count=1
  25. Thread-8 - count=2
  26. Thread-7 - count=3
  27. Thread-6 - count=4
  28. Thread-9 - count=5
  29. Thread-5 - count=6
  30. Thread-3 - count=7
  31. Thread-4 - count=8
  32. Thread-2 - count=9
  33. Thread-1 - count=10
  1. public class MethodB {
  2. public synchronized void process(){
  3. Constant.count++;
  4. System.out.println(Thread.currentThread().getName()+" - count="+Constant.count);
  5. }
  6. }
  7. public class MyThread02 {
  8. public static void main(String[] args) {
  9. MethodB methodB = new MethodB();
  10. for(int i=0;i<10;i++){
  11. Thread t = new Thread(new Runnable() {
  12. @Override
  13. public void run() {
  14. methodB.process();
  15. }
  16. });
  17. t.start();
  18. }
  19. }
  20. }
  21. -------------
  22. Thread-0 - count=1
  23. Thread-9 - count=2
  24. Thread-8 - count=3
  25. Thread-7 - count=4
  26. Thread-6 - count=5
  27. Thread-5 - count=6
  28. Thread-4 - count=7
  29. Thread-3 - count=8
  30. Thread-2 - count=9
  31. Thread-1 - count=10

线程同步,指某一个时刻,指允许一个线程来访问共享资源,线程同步其实是对对象加锁,如果对象中的方法都是同步方法,那么某一时刻只能执行一个方法,采用线程同步解决以上的问题,我们只要保证线程一操作count时,另一个线程不允许操作即可,只有线程一使用完成count后,再让线程二来使用count变量

3、为每一个线程创建一个对象来解决线程安全问题

  1. public class ThreadTest13 {
  2. public static void main(String[] args) {
  3. Runnable r1 = new Processor();
  4. Thread t1 = new Thread(r1, "t1");
  5. t1.start();
  6. //再次创建Processor对象
  7. //每个线程拥有自己的对象
  8. Runnable r2 = new Processor();
  9. Thread t2 = new Thread(r2, "t2");
  10. t2.start();
  11. }
  12. }
  13. class Processor implements Runnable {
  14. //定义成员变量s,作为累加变量
  15. private int s = 0;
  16. public void run() {
  17. for (int i=0; i<10; i++) {
  18. s+=i;
  19. }
  20. System.out.println(Thread.currentThread().getName() + ", s=" + s);
  21. s = 0;
  22. }
  23. }

以上输出完全正确,每个线程操作的是自己的对象,没有操作共享的资源

4、Java多线程之死锁的出现和解决方法

1、什么是死锁?

死锁是这样一种情形:多个线程同时被阻塞,它们中的一个或者全部都在等待某个资源被释放.
形象的说就是:一个宝藏需要两把钥匙来打开,同时间正好来了两个人,他们一人一把钥匙,但是双方都再等着对方能交出钥匙来打开宝藏,谁都没释放自己的那把钥匙.就这样这俩人一直僵持下去,直到开发人员发现这个局面.

2、synchronized嵌套.

死锁例子

  1. class ProductThreadA implements Runnable{
  2. @Override
  3. public void run() {
  4. synchronized (Dead.lockA){
  5. System.out.println("ThreadA lock lockA");
  6. synchronized (Dead.lockB){
  7. System.out.println("ThreadA lock lockB");
  8. }
  9. }
  10. }
  11. }
  12. class ProductThreadB implements Runnable{
  13. @Override
  14. public void run() {
  15. synchronized (Dead.lockB){
  16. System.out.println("ThreadB lock lockB");
  17. synchronized (Dead.lockA){
  18. System.out.println("ThreadB lock lockA");
  19. }
  20. }
  21. }
  22. }
  23. class Dead {
  24. final static Object lockA = new Object();
  25. final static Object lockB = new Object();
  26. public static void main(String[] args) {
  27. //这里运行线程
  28. ProductThreadA productThreadA = new ProductThreadA();
  29. ProductThreadB productThreadB = new ProductThreadB();
  30. Thread threadA = new Thread(productThreadA);
  31. Thread threadB = new Thread(productThreadB);
  32. threadA.start();
  33. threadB.start();
  34. }
  35. }


3、死锁出现的原因

同时竞争同一个资源(锁)

4、死锁的解决方法

保证不存在竞争资源(锁)即可