1、为什么需要同步
【示例代码】
public class Constant {
public static int count = 0;
}
public class MethodA {
public void process(){
Constant.count++;
System.out.println(Thread.currentThread().getName()+" - count="+Constant.count);
}
}
public class MyThread01 {
public static void main(String[] args) {
for(int i=0;i<10;i++){
Thread t = new Thread(new Runnable() {
@Override
public void run() {
MethodA methodA = new MethodA();
methodA.process();
}
});
t.start();
}
}
}
--------------
Thread-4 - count=4
Thread-9 - count=10
Thread-6 - count=9
Thread-5 - count=8
Thread-0 - count=7
Thread-1 - count=4
Thread-2 - count=4
Thread-3 - count=6
Thread-7 - count=4
Thread-8 - count=5
【示例代码】
public class MyThread02 {
public static void main(String[] args) {
MethodB methodB = new MethodB();
for(int i=0;i<10;i++){
Thread t = new Thread(new Runnable() {
@Override
public void run() {
methodB.process();
}
});
t.start();
}
}
}
-------------
Thread-5 - count=6
Thread-1 - count=10
Thread-0 - count=6
Thread-8 - count=9
Thread-2 - count=9
Thread-4 - count=7
Thread-3 - count=8
Thread-6 - count=6
Thread-7 - count=6
Thread-9 - count=6
2、使用线程同步
public class MethodA {
public void process(){
synchronized(Constant.class){
Constant.count++;
System.out.println(Thread.currentThread().getName()+" - count="+Constant.count);
}
}
}
public class MyThread01 {
public static void main(String[] args) {
for(int i=0;i<10;i++){
Thread t = new Thread(new Runnable() {
@Override
public void run() {
MethodA methodA = new MethodA();
methodA.process();
}
});
t.start();
}
}
}
--------------
Thread-0 - count=1
Thread-8 - count=2
Thread-7 - count=3
Thread-6 - count=4
Thread-9 - count=5
Thread-5 - count=6
Thread-3 - count=7
Thread-4 - count=8
Thread-2 - count=9
Thread-1 - count=10
public class MethodB {
public synchronized void process(){
Constant.count++;
System.out.println(Thread.currentThread().getName()+" - count="+Constant.count);
}
}
public class MyThread02 {
public static void main(String[] args) {
MethodB methodB = new MethodB();
for(int i=0;i<10;i++){
Thread t = new Thread(new Runnable() {
@Override
public void run() {
methodB.process();
}
});
t.start();
}
}
}
-------------
Thread-0 - count=1
Thread-9 - count=2
Thread-8 - count=3
Thread-7 - count=4
Thread-6 - count=5
Thread-5 - count=6
Thread-4 - count=7
Thread-3 - count=8
Thread-2 - count=9
Thread-1 - count=10
线程同步,指某一个时刻,指允许一个线程来访问共享资源,线程同步其实是对对象加锁,如果对象中的方法都是同步方法,那么某一时刻只能执行一个方法,采用线程同步解决以上的问题,我们只要保证线程一操作count时,另一个线程不允许操作即可,只有线程一使用完成count后,再让线程二来使用count变量
3、为每一个线程创建一个对象来解决线程安全问题
public class ThreadTest13 {
public static void main(String[] args) {
Runnable r1 = new Processor();
Thread t1 = new Thread(r1, "t1");
t1.start();
//再次创建Processor对象
//每个线程拥有自己的对象
Runnable r2 = new Processor();
Thread t2 = new Thread(r2, "t2");
t2.start();
}
}
class Processor implements Runnable {
//定义成员变量s,作为累加变量
private int s = 0;
public void run() {
for (int i=0; i<10; i++) {
s+=i;
}
System.out.println(Thread.currentThread().getName() + ", s=" + s);
s = 0;
}
}
以上输出完全正确,每个线程操作的是自己的对象,没有操作共享的资源
4、Java多线程之死锁的出现和解决方法
1、什么是死锁?
死锁是这样一种情形:多个线程同时被阻塞,它们中的一个或者全部都在等待某个资源被释放.
形象的说就是:一个宝藏需要两把钥匙来打开,同时间正好来了两个人,他们一人一把钥匙,但是双方都再等着对方能交出钥匙来打开宝藏,谁都没释放自己的那把钥匙.就这样这俩人一直僵持下去,直到开发人员发现这个局面.
2、synchronized嵌套.
死锁例子
class ProductThreadA implements Runnable{
@Override
public void run() {
synchronized (Dead.lockA){
System.out.println("ThreadA lock lockA");
synchronized (Dead.lockB){
System.out.println("ThreadA lock lockB");
}
}
}
}
class ProductThreadB implements Runnable{
@Override
public void run() {
synchronized (Dead.lockB){
System.out.println("ThreadB lock lockB");
synchronized (Dead.lockA){
System.out.println("ThreadB lock lockA");
}
}
}
}
class Dead {
final static Object lockA = new Object();
final static Object lockB = new Object();
public static void main(String[] args) {
//这里运行线程
ProductThreadA productThreadA = new ProductThreadA();
ProductThreadB productThreadB = new ProductThreadB();
Thread threadA = new Thread(productThreadA);
Thread threadB = new Thread(productThreadB);
threadA.start();
threadB.start();
}
}
3、死锁出现的原因
同时竞争同一个资源(锁)
4、死锁的解决方法
保证不存在竞争资源(锁)即可