EduCoder Java高级特性 - 多线程基础(3)线程同步

第1关:并发编程的三个概念

任务描述

在我们进行应用开发的时候,常常会关注网站的并发,如果网站的用户量很多,当这些用户同时访问一个服务的时候,我们的服务器就会接收到大量的并发请求,处理好这些并发请求是一个合格程序员必须要完成的工作。

理解并发编程的三个概念对于我们更好的开发高并发的Web应用有很大的帮助。

本关的任务就是理解并发编程的三个重要概念并完成右侧选择题。

  • 1、在并发编程中,我们需要以下哪几个特性来保持多线程程序执行正确(ABD )

    A、可见性
    B、原子性
    C、并发性
    D、有序性
  • 2、请分析以下语句哪些是原子操作(AB )

    A、int a = 3;
    B、boolean flag = false;
    C、a–;
    D、a =a *a
  • 3、以下代码的执行结果是(E)

    1. public class Test {
    2. public int inc = 0;
    3.  
    4. public void increase() {
    5. inc++;
    6. }
    7.  
    8. public static void main(String[] args) {
    9. final Test test = new Test();
    10. for(int i=0;i<10;i++){
    11. new Thread(){
    12. public void run() {
    13. for(int j=0;j<1000;j++)
    14. test.increase();
    15. };
    16. }.start();
    17. }
    18.  
    19. while(Thread.activeCount()>1) //保证前面的线程都执行完
    20. Thread.yield();
    21. System.out.println(test.inc);
    22. }
    23. }
    A、10000
    B、9870
    C、大于10000
    D、小于10000
    E、不一定,大概率小于一万

第2关:使用synchronized关键字同步线程

任务描述

本关任务:使右侧代码中的insert方法在同一时刻只有一个线程能访问。

编程要求

请仔细阅读右侧代码,根据方法内的提示,在Begin - End区域内进行代码补充,具体任务如下:

  • 使num变量在同一时刻只能有一个线程可以访问。

测试说明

使程序的输出结果如下:

EduCoder Java高级特性 - 多线程基础(3)线程同步_第1张图片

通关代码

package step2;

public class Task {
	public static void main(String[] args) {	
		final insertData insert = new insertData();
		
		for (int i = 0; i < 3; i++) {
			new Thread(new Runnable() {
				public void run() {
					insert.insert(Thread.currentThread());
				}
			}).start();
		}		
	}
}
class insertData{
	public static int num =0;
	/********* Begin *********/
	public synchronized void insert(Thread thread){
		for (int i = 0; i <= 5; i++) {
			num++;
			System.out.println(num);
		}
	}
	/********* End *********/
}

第3关:使用线程锁(Lock)实现线程同步

任务描述

本关任务:使用Lock,实现对于某一块代码的互斥访问

编程要求

请仔细阅读右侧代码,根据方法内的提示,在Begin - End区域内进行代码补充。 ####测试说明

使得程序输出如下结果(因为线程的执行顺序是随机的可能需要你评测多次):

EduCoder Java高级特性 - 多线程基础(3)线程同步_第2张图片

通关代码

package step3;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class Task {
	public static void main(String[] args) {
		final Insert insert = new Insert();
		Thread t1 = new Thread(new Runnable() {
			public void run() {
				insert.insert(Thread.currentThread());
			}
		});
		Thread t2 = new Thread(new Runnable() {
			public void run() {
				insert.insert(Thread.currentThread());
			}
		});
		Thread t3 = new Thread(new Runnable() {
			public void run() {
				insert.insert(Thread.currentThread());
			}
		});
		// 设置线程优先级
		t1.setPriority(Thread.MAX_PRIORITY);
		t2.setPriority(Thread.NORM_PRIORITY);
		t3.setPriority(Thread.MIN_PRIORITY);

		t1.start();
		t2.start();
		t3.start();

	}
}
class Insert {
	public static int num;
	// 在这里定义Lock
	private Lock lock = new ReentrantLock(); 
	public void insert(Thread thread) {
		/********* Begin *********/
		if(lock.tryLock()){
			try{
				System.out.println(thread.getName()+"得到了锁");
				for (int i = 0; i < 5; i++) {
					num++;
					System.out.println(num);
				}
			}finally{
				System.out.println(thread.getName()+"释放了锁");
				lock.unlock();
			}
		}else{
			System.out.println(thread.getName()+"获取锁失败");
		}
	}
		/********* End *********/
}

在这种情况之下,程序输出所需要的结果可能需要多次,因为线程的执行顺序是随机的,我们可以通过sleep()方法来改进程序,这样就不需要设置线程优先级。

通关代码(改进)

package step3;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class Task {
    public static void main(String[] args) throws InterruptedException {
        final Insert insert = new Insert();
        Thread t1 = new Thread(new Runnable() {
            public void run() {
                insert.insert(Thread.currentThread());
            }
        });
        Thread t2 = new Thread(new Runnable() {
            public void run() {
                insert.insert(Thread.currentThread());
            }
        });
        Thread t3 = new Thread(new Runnable() {
            public void run() {
                insert.insert(Thread.currentThread());
            }
        });
        // 设置线程优先级
        /*
        t1.setPriority(Thread.MAX_PRIORITY);
        t2.setPriority(Thread.NORM_PRIORITY);
        t3.setPriority(Thread.MIN_PRIORITY);

        t1.start();
        t2.start();
        t3.start();
        */
        t1.start();
        t2.sleep(500);
        t2.start();
        t3.sleep(1000);
        t3.start();
    }
}

class Insert {
    public static int num;
    // 在这里定义Lock
    private Lock lock = new ReentrantLock();

    public void insert(Thread thread) {
        /********* Begin *********/
        if (lock.tryLock()) {
            try {
                System.out.println(thread.getName() + "得到了锁");
                for (int i = 0; i < 5; i++) {
                    num++;
                    System.out.println(num);
                }
            } finally {
                System.out.println(thread.getName() + "释放了锁");
                lock.unlock();
            }
        } else {
            System.out.println(thread.getName() + "获取锁失败");
        }
    }
    /********* End *********/
}

第4关:使用volatile实现变量的可见性

任务描述

本关任务:使用volatile关键字与同步实现右侧程序输出10000

编程要求

请仔细阅读右侧代码,根据方法内的提示,在Begin - End区域内进行代码补充。 ####测试说明

预期输出:10000

提示:可以使用两种方式实现原子性,所以本关有多种方式都可以通关。

通关代码

package step4;

public class Task {
	public volatile int inc = 0;
	//请在此添加实现代码
	/********** Begin **********/
	public synchronized void increase() {
		inc++;
	}
	/********** End **********/
	public static void main(String[] args) {
		final Task test = new Task();
		for (int i = 0; i < 10; i++) {
			new Thread() {
				public void run() {
					for (int j = 0; j < 1000; j++)
						test.increase();
				};
			}.start();
		}
		while (Thread.activeCount() > 1) // 保证前面的线程都执行完
			Thread.yield();
		System.out.println(test.inc);
	}
}

 

你可能感兴趣的:(java,多线程)