JUC多线程并发——8锁
8锁:
1.标准访问,请问先打印邮件还是短信?
2.邮件方法暂停4秒钟,请问先打印邮件还是短信?
3.新增一个普通方法hello(),请问先打印邮件还是hello?
4.两部手机,请问先打印邮件还是短信?
5.两个静态同步方法,同一部手机,请问先打印邮件还是短信?
6.两个静态同步方法,2部手机,请问先打印邮件还是两部手机,请问先打印邮件还是短信?
7.1个普通同步方法,1个静态同步方法,1部手机,请问先打印邮件还是短信?
8.1个普通同步方法,1个静态同步方法,2部手机,请问先打印邮件还是短信?
1.标准访问,请问先打印邮件还是短信?
class Phone{
public synchronized void sendEmail() throws Exception {
System.out.println("----sendEmail");
}
public synchronized void sendMS() throws Exception {
System.out.println("----sendMS");
}
}
public class Lock8 {
public static void main(String[] args) throws InterruptedException {
Phone phone = new Phone();
new Thread(()->{
try {
phone.sendEmail();
} catch (Exception e) {
e.printStackTrace();
}
},"A").start();
new Thread(()->{
try {
phone.sendMS();
} catch (Exception e) {
e.printStackTrace();
}
},"B").start();
}
}
这里的结果并不是按顺序得到的,而是两个线程互相抢占锁资源。
只是线程A运气更好,CPU先调度A线程,A先抢到了锁对象,从而调用同步方法sendEmail()
。
在A释放锁对象后,B才能占用锁对象,调用同步方法sendMS()
。
如果要的效果是:线程A先执行,线程B后执行。可以在线程A后面添加Thread.sleep(1000);
或TimeUnit.SECONDS.sleep(1);
。为方便演示后面的锁都添加延时。
这样就是固定顺序,先线程A后线程B,出现上面的结果是理所当然的。
下面这个例子,就是演示了两个线程互相抢占锁资源。
class Phone{
public synchronized void sendEmail() throws Exception {
System.out.println("----sendEmail");
}
public synchronized void sendMS() throws Exception {
System.out.println("----sendMS");
}
}
public class Lock8 {
public static void main(String[] args) throws InterruptedException {
Phone phone = new Phone();
new Thread(()->{
try {
for (int i = 0; i < 10; i++) {
phone.sendEmail();
}
} catch (Exception e) {
e.printStackTrace();
}
},"A").start();
new Thread(()->{
try {
for (int i = 0; i < 10; i++) {
phone.sendMS();
}
} catch (Exception e) {
e.printStackTrace();
}
},"B").start();
}
}
2.邮件方法暂停4秒钟,请问先打印邮件还是短信?
class Phone{
public synchronized void sendEmail() throws Exception {
TimeUnit.SECONDS.sleep(4);
System.out.println("----sendEmail");
}
public synchronized void sendMS() throws Exception {
System.out.println("----sendMS");
}
}
public class Lock8 {
public static void main(String[] args) throws Exception {
Phone phone = new Phone();
new Thread(()->{
try {
phone.sendEmail();
} catch (Exception e) {
e.printStackTrace();
}
},"A").start();
Thread.sleep(200);
new Thread(()->{
try {
phone.sendMS();
} catch (Exception e) {
e.printStackTrace();
}
},"B").start();
}
}
很明显,A线程先占用锁对象,过4秒才会释放锁对象,B线程阻塞;4秒后B线程再占用锁对象。
3.新增一个普通方法hello(),请问先打印邮件还是hello?
class Phone{
public synchronized void sendEmail() throws Exception {
TimeUnit.SECONDS.sleep(4);
System.out.println("----sendEmail");
}
public synchronized void sendMS() throws Exception {
System.out.println("----sendMS");
}
public void hello(){
System.out.println("----hello");
}
}
public class Lock8 {
public static void main(String[] args) throws Exception {
Phone phone = new Phone();
new Thread(()->{
try {
phone.sendEmail();
} catch (Exception e) {
e.printStackTrace();
}
},"A").start();
Thread.sleep(200);
new Thread(()->{
try {
phone.hello();
} catch (Exception e) {
e.printStackTrace();
}
},"B").start();
}
}
普通方法不参与锁对象的抢占,他执行他的,我执行我的。
线程A先调用sendEmail()
进入sleep,虽然sleep过程不释放锁资源,但是线程B调用的hello()
不是同步方法,不会等待锁资源释放,直接执行。
4.两部手机,请问先打印邮件还是短信?
class Phone{
public synchronized void sendEmail() throws Exception {
TimeUnit.SECONDS.sleep(4);
System.out.println("----sendEmail");
}
public synchronized void sendMS() throws Exception {
System.out.println("----sendMS");
}
}
public class Lock8 {
public static void main(String[] args) throws Exception {
Phone phone1 = new Phone();
Phone phone2 = new Phone();
new Thread(()->{
try {
phone1.sendEmail();
} catch (Exception e) {
e.printStackTrace();
}
},"A").start();
Thread.sleep(200);
new Thread(()->{
try {
phone2.sendMS();
} catch (Exception e) {
e.printStackTrace();
}
},"B").start();
}
}
此时,由于是分别使用两个锁对象调用方法,执行过程中两个线程互不干扰,线程B不会等待锁对象释放,直接执行phone2
对象的sendMS()
方法。
5.两个静态同步方法,同一部手机,请问先打印邮件还是短信?
class Phone{
public static synchronized void sendEmail() throws Exception {
TimeUnit.SECONDS.sleep(4);
System.out.println("----sendEmail");
}
public static synchronized void sendMS() throws Exception {
System.out.println("----sendMS");
}
}
public class Lock8 {
public static void main(String[] args) throws Exception {
Phone phone = new Phone();
new Thread(()->{
try {
phone.sendEmail();
} catch (Exception e) {
e.printStackTrace();
}
},"A").start();
Thread.sleep(200);
new Thread(()->{
try {
phone.sendMS();
} catch (Exception e) {
e.printStackTrace();
}
},"B").start();
}
}
这个应该很好理解,主要看6
6.两个静态同步方法,2部手机,请问先打印邮件还是两部手机,请问先打印邮件还是短信?
class Phone{
public static synchronized void sendEmail() throws Exception {
TimeUnit.SECONDS.sleep(4);
System.out.println("----sendEmail");
}
public static synchronized void sendMS() throws Exception {
System.out.println("----sendMS");
}
}
public class Lock8 {
public static void main(String[] args) throws Exception {
Phone phone1 = new Phone();
Phone phone2 = new Phone();
new Thread(()->{
try {
phone1.sendEmail();
} catch (Exception e) {
e.printStackTrace();
}
},"A").start();
Thread.sleep(200);
new Thread(()->{
try {
phone2.sendMS();
} catch (Exception e) {
e.printStackTrace();
}
},"B").start();
}
}
static作用于方法上,说明这个方法属于类。可以这么调用:Phone.sendEmail();
而static sychronized相当于锁了类模板,其他线程再调用类模板中的静态同步方法必须等待之前的锁释放。
7.1个普通同步方法,1个静态同步方法,1部手机,请问先打印邮件还是短信?
class Phone{
public static synchronized void sendEmail() throws Exception {
TimeUnit.SECONDS.sleep(4);
System.out.println("----sendEmail");
}
public synchronized void sendMS() throws Exception {
System.out.println("----sendMS");
}
}
public class Lock8 {
public static void main(String[] args) throws Exception {
Phone phone = new Phone();
new Thread(()->{
try {
phone.sendEmail();
} catch (Exception e) {
e.printStackTrace();
}
},"A").start();
Thread.sleep(200);
new Thread(()->{
try {
phone.sendMS();
} catch (Exception e) {
e.printStackTrace();
}
},"B").start();
}
}
由于一个锁的是Person.class
类模板,一个锁的是person
对象,虽然是一部手机,但是不是同一个锁,他执行他的,我执行我的。
8.1个普通同步方法,1个静态同步方法,2部手机,请问先打印邮件还是短信?
class Phone{
public synchronized void sendEmail() throws Exception {
TimeUnit.SECONDS.sleep(4);
System.out.println("----sendEmail");
}
public static synchronized void sendMS() throws Exception {
System.out.println("----sendMS");
}
}
public class Lock8 {
public static void main(String[] args) throws Exception {
Phone phone1 = new Phone();
Phone phone2 = new Phone();
new Thread(()->{
try {
phone1.sendEmail();
} catch (Exception e) {
e.printStackTrace();
}
},"A").start();
Thread.sleep(200);
new Thread(()->{
try {
phone2.sendMS();
} catch (Exception e) {
e.printStackTrace();
}
},"B").start();
}
}
phone1.sendEmail();
普通同步方法 锁的是person1
对象
phone2.sendMS();
静态同步方法 锁的是Person.class
类模板
两部手机,锁的东西也不一样,自然是互不影响。
以上均为个人学习过程中记录的所思所想,代码和文章亲自手打。
如有错误,烦请指出。