静态同步synchronized方法和synchronized(class) 同步块
synchronized加到静态方法上,是给class类上锁,而synchronized关键字加到非static静态方法上是给对象上锁。
public class Service {
synchronized public static void printA(){
System.out.println("线程"+Thread.currentThread().getName()+"在"+
System.currentTimeMillis()+"进入A");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("线程"+Thread.currentThread().getName()+"在"+
System.currentTimeMillis()+"进入A");
}
synchronized public static void printB(){
System.out.println("线程"+Thread.currentThread().getName()+"在"+
System.currentTimeMillis()+"进入B");
System.out.println("线程"+Thread.currentThread().getName()+"在"+
System.currentTimeMillis()+"进入B");
}
synchronized public void printC(){
System.out.println("线程"+Thread.currentThread().getName()+"在"+System.currentTimeMillis()+"进入C");
System.out.println("线程"+Thread.currentThread().getName()+"在"+System.currentTimeMillis()+"进入C");
}
}
线程A,线程B,线程C执行方法A,B,C 结果:方法A和方法B同步执行,方法C由于是上对象的锁和其他线程是异步执行的
synchronized(class){}同步块,也是获取class对象的锁,不同线程执行a,b方法,也会是同步的效果
public class Service {
public void printA(){
synchronized (Service.class) {
System.out.println("线程"+Thread.currentThread().getName()+"在"+
System.currentTimeMillis()+"进入A");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("线程"+Thread.currentThread().getName()+"在"+
System.currentTimeMillis()+"进入A");
}
}
public void printB(){
synchronized (Service.class) {
System.out.println("线程"+Thread.currentThread().getName()+"在"+
System.currentTimeMillis()+"进入B");
System.out.println("线程"+Thread.currentThread().getName()+"在"+
System.currentTimeMillis()+"进入B");
}
}
}
synchronized使用过程中需要注意String常量池的特性
string做为锁对象,“AA”和后面的AA是由于字符串常量池特性,是同一个对象,因此下面的程序是同步执行,
如果改为new object(),每次调用方法时候是不同的锁对象,结果就会是异步执行
public class Service {
public void print(String stringparam){
synchronized (stringparam) {
while(true){
System.out.println(Thread.currentThread().getName());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args) {
final Service service = new Service();
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
service.print("AA");
}
},"A");
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
service.print("AA");
}
},"B");
t1.start();t2.start();
}
}
多线程的死锁形成的原因:
1. 两个线程相互等待对方释放锁
2. 一个线程持有锁,由于死循环没有释放,导致另一个线程无限等待
/**
* 死锁,两个线程相互等待锁,造成死锁
* @author zhouy
*
*/
public class DeadThread {
public Object lock1 = new Object();
public Object lock2 = new Object();
public void deadLock(){
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
synchronized (lock1) {
System.out.println("t1获取到lock1的锁");
try {
Thread.currentThread().sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (lock2) {
System.out.println("t1获取到lock2的锁");
}
}
}
});
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
synchronized (lock2) {
synchronized (lock1) {
System.out.println("t2获取到lock1的锁");
}
}
}
});
t1.start();
t2.start();
}
public static void main(String[] args) {
new DeadThread().deadLock();
}
}
内置类同步
内置类的同步也是一样的,只要关注锁对象是否相同,锁对象相同的,线程就是同步执行的,否则就是异步,
而且,只要锁对象不变,锁对象的属性改变,也不会影响线程同步
public class Service {
synchronized public void testMethod(UserInfo user){
synchronized (user) {
user.setUsername("abcde");
System.out.println(Thread.currentThread().getName());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+" end! "+System.currentTimeMillis());
}
}
synchronized public void test(UserInfo user){
synchronized (user) {
user.setPassword("abcde");
System.out.println(Thread.currentThread().getName());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+" end! "+System.currentTimeMillis());
}
}
public static void main(String[] args) {
final Service service = new Service();
final UserInfo user = new UserInfo();//final修饰 引用不可变,对象还是可变的
Thread t = new Thread(new Runnable() {
@Override
public void run() {
service.testMethod(user);
}
}, "A");
t.start();
service.test(user);
}
}