{"id":13617316,"url":"https://github.com/oldratlee/fucking-java-concurrency","last_synced_at":"2025-05-14T18:00:17.001Z","repository":{"id":37450976,"uuid":"20853572","full_name":"oldratlee/fucking-java-concurrency","owner":"oldratlee","description":"🎏 Simple showcases of java concurrency problems, seeing 🙈 is believing 🐵","archived":false,"fork":false,"pushed_at":"2025-04-02T06:37:10.000Z","size":144,"stargazers_count":1170,"open_issues_count":2,"forks_count":335,"subscribers_count":61,"default_branch":"master","last_synced_at":"2025-05-14T13:25:31.080Z","etag":null,"topics":["concurrency","concurrency-gotchas","concurrency-issue","concurrency-problem","concurrent-programming","deadlock","demo","java","multi-threading","multithreading","parallelism","showcase","sync","synchronization","thread-safety"],"latest_commit_sha":null,"homepage":"https://github.com/oldratlee/fucking-java-concurrency","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/oldratlee.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2014-06-15T11:03:52.000Z","updated_at":"2025-05-12T10:09:41.000Z","dependencies_parsed_at":"2023-11-10T14:36:37.787Z","dependency_job_id":"5b53ef5b-21e9-4ba4-b01a-0dcac37b6fba","html_url":"https://github.com/oldratlee/fucking-java-concurrency","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oldratlee%2Ffucking-java-concurrency","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oldratlee%2Ffucking-java-concurrency/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oldratlee%2Ffucking-java-concurrency/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oldratlee%2Ffucking-java-concurrency/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/oldratlee","download_url":"https://codeload.github.com/oldratlee/fucking-java-concurrency/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254198452,"owners_count":22030964,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["concurrency","concurrency-gotchas","concurrency-issue","concurrency-problem","concurrent-programming","deadlock","demo","java","multi-threading","multithreading","parallelism","showcase","sync","synchronization","thread-safety"],"created_at":"2024-08-01T20:01:39.890Z","updated_at":"2025-05-14T18:00:16.278Z","avatar_url":"https://github.com/oldratlee.png","language":"Java","readme":"# \u003cdiv align=\"center\"\u003e 🎏 fucking-java-concurrency\u003c/div\u003e\n\n\u003cp align=\"center\"\u003e\n\u003ca href=\"https://github.com/oldratlee/fucking-java-concurrency/actions/workflows/ci.yaml\"\u003e\u003cimg src=\"https://img.shields.io/github/actions/workflow/status/oldratlee/fucking-java-concurrency/ci.yaml?branch=master\u0026logo=github\u0026logoColor=white\" alt=\"Github Workflow Build Status\"\u003e\u003c/a\u003e\n\u003ca href=\"https://openjdk.java.net/\"\u003e\u003cimg src=\"https://img.shields.io/badge/Java-8+-339933?logo=openjdk\u0026logoColor=white\" alt=\"Java support\"\u003e\u003c/a\u003e\n\u003ca href=\"https://www.apache.org/licenses/LICENSE-2.0.html\"\u003e\u003cimg src=\"https://img.shields.io/github/license/oldratlee/fucking-java-concurrency?color=4D7A97\u0026logo=apache\" alt=\"License\"\u003e\u003c/a\u003e\n\u003ca href=\"https://github.com/oldratlee/fucking-java-concurrency/stargazers\"\u003e\u003cimg src=\"https://img.shields.io/github/stars/oldratlee/fucking-java-concurrency?style=flat\" alt=\"GitHub Stars\"\u003e\u003c/a\u003e\n\u003ca href=\"https://github.com/oldratlee/fucking-java-concurrency/fork\"\u003e\u003cimg src=\"https://img.shields.io/github/forks/oldratlee/fucking-java-concurrency?style=flat\" alt=\"GitHub Forks\"\u003e\u003c/a\u003e\n\u003ca href=\"https://github.com/oldratlee/fucking-java-concurrency/graphs/contributors\"\u003e\u003cimg src=\"https://img.shields.io/github/contributors/oldratlee/fucking-java-concurrency\" alt=\"GitHub Contributors\"\u003e\u003c/a\u003e\n\u003ca href=\"https://github.com/oldratlee/fucking-java-concurrency\"\u003e\u003cimg src=\"https://img.shields.io/github/repo-size/oldratlee/fucking-java-concurrency\" alt=\"GitHub repo size\"\u003e\u003c/a\u003e\n\u003ca href=\"https://gitpod.io/#https://github.com/oldratlee/fucking-java-concurrency\"\u003e\u003cimg src=\"https://img.shields.io/badge/Gitpod-ready to code-339933?label=gitpod\u0026logo=gitpod\u0026logoColor=white\" alt=\"gitpod: Ready to Code\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n----------------------------------------\n\n📖 English Documentation | [📖 中文文档](docs/zh-CN/README.md)\n\nSimple showcases of `Java` concurrency problems, seeing 🙈 is believing 🐵.\n\n## 🍎 Reasons to organize Demo\n\n- The actual phenomenon that can be observed 🙈 is more intuitive and more trustworthy than the concurrency principle mentioned 🙊.\n- The `Java` language standard library supports threads, multithreading is heavily used in the language itself (such as `GC`) and applications (the server side).\n- Concurrency program design, in the analysis and implementation, the complexity is greatly increased. If you do not fully understand and systematically analyze the concurrent logic, and write code at will, it is not an exaggeration to describe such a program as \"**accidentally**\" running with the correct result.  \n    - The demos here do not give explanations and discussions, and they are all entry-level :neckbeard: . For more information, please loop up the concurrency materials by yourself.\n\nExamples of concurrency problems you encountered in development are welcome to provide ([submit Issue](https://github.com/oldratlee/fucking-java-concurrency/issues)) or share ([pull request after Fork](https://github.com/oldratlee/fucking-java-concurrency/fork))! 😘\n\n----------------------------------------\n\n\u003cimg src=\"docs/dining-philosophers-problem.jpg\" width=\"30%\" align=\"right\" /\u003e\n\n\u003c!-- START doctoc generated TOC please keep comment here to allow auto update --\u003e\n\u003c!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE --\u003e\n\n- [🍺 Update without synchronization cannot be read in another thread](#-update-without-synchronization-cannot-be-read-in-another-thread)\n    - [Demo description](#demo-description)\n    - [Problem statement](#problem-statement)\n    - [Quickly run](#quickly-run)\n- [🍺 Infinite loop of `HashMap`](#-infinite-loop-of-hashmap)\n    - [Demo description](#demo-description-1)\n    - [Problem statement](#problem-statement-1)\n    - [Quickly run](#quickly-run-1)\n- [🍺 Combined state read invalid combination](#-combined-state-read-invalid-combination)\n    - [Demo description](#demo-description-2)\n    - [Problem statement](#problem-statement-2)\n    - [Quickly run](#quickly-run-2)\n- [🍺 `long` variable read invalid value](#-long-variable-read-invalid-value)\n    - [Demo description](#demo-description-3)\n    - [Problem statement](#problem-statement-3)\n    - [Quickly run](#quickly-run-3)\n- [🍺 the result of concurrency count without synchronization is wrong](#-the-result-of-concurrency-count-without-synchronization-is-wrong)\n    - [Demo description](#demo-description-4)\n    - [Problem statement](#problem-statement-4)\n    - [Quickly run](#quickly-run-4)\n- [🍺 Synchronization on mutable fields](#-synchronization-on-mutable-fields)\n    - [Demo description](#demo-description-5)\n    - [Problem statement](#problem-statement-5)\n    - [Quickly run](#quickly-run-5)\n- [🍺 Deadlock caused by the symmetric locks](#-deadlock-caused-by-the-symmetric-locks)\n    - [Demo description](#demo-description-6)\n    - [Problem statement](#problem-statement-6)\n    - [Quickly run](#quickly-run-6)\n- [🍺 Livelock caused by reentrant locks](#-livelock-caused-by-reentrant-locks)\n    - [Demo description](#demo-description-7)\n    - [Problem statement](#problem-statement-7)\n    - [Quickly run](#quickly-run-7)\n- [🍺 Instruction reordering causes non-final field variable read error](#-instruction-reordering-causes-non-final-field-variable-read-error)\n    - [Demo description](#demo-description-8)\n    - [Problem statement](#problem-statement-8)\n    - [Quickly run](#quickly-run-8)\n\n\u003c!-- END doctoc generated TOC please keep comment here to allow auto update --\u003e\n\n----------------------------------------\n\n## 🍺 Update without synchronization cannot be read in another thread\n\nDemo class [`NoPublishDemo`](src/main/java/fucking/concurrency/demo/NoPublishDemo.java).\n\n### Demo description\n\nSet the field `stop` to `true` in the `main` thread to control the exit of the task thread started in `main`.\n\n### Problem statement\n\nAfter the `main` thread field `stop` is `true`, the task thread continues to run, that is, no new value has been read in the task thread.\n\n### Quickly run\n\n```bash\n./mvnw compile exec:java -Dexec.mainClass=fucking.concurrency.demo.NoPublishDemo\n```\n\n## 🍺 Infinite loop of `HashMap`\n\nThis problem has been explained in many places.\n\nThe Demo class [`HashMapHangDemo`](src/main/java/fucking/concurrency/demo/HashMapHangDemo.java) can reproduce this problem.\n\n### Demo description\n\nTwo task threads are opened in the main thread to perform the put operation of `HashMap`. The main thread does the get operation.\n\n### Problem statement\n\nThe main thread Block is determined by no continuous output, that is, the endless loop of `HashMap` appears.\n\n### Quickly run\n\n```bash\n./mvnw compile exec:java -Dexec.mainClass=fucking.concurrency.demo.HashMapHangDemo\n```\n\n## 🍺 Combined state read invalid combination\n\nWhen programming, multiple state records will be required (state can be a `POJO` object or `int`s, etc.).\n\nIt is often seen that the multi-state read and write code is not synchronized, and the person who write it will naturally ignore the issue of thread safety.\n\nInvalid combinations are combinations that have never been set.\n\n### Demo description\n\nThe main thread modifies multiple states. For the convenience of checking, each write has a fixed relationship: the second state is twice the value of the first state. Read multiple states in a task thread.\nDemo class [`InvalidCombinationStateDemo`](src/main/java/fucking/concurrency/demo/InvalidCombinationStateDemo.java).\n\n### Problem statement\n\nThe second state read in the task thread is not twice the value of the first state, that is, an invalid value.\n\n### Quickly run\n\n```bash\n./mvnw compile exec:java -Dexec.mainClass=fucking.concurrency.demo.InvalidCombinationStateDemo\n```\n\n## 🍺 `long` variable read invalid value\n\nAn invalid value is a value that has never been set.\n\nReading and writing of `long` variables is not atomic and will be divided into two 4-byte operations.\n\nDemo class [`InvalidLongDemo`](src/main/java/fucking/concurrency/demo/InvalidLongDemo.java).\n\n### Demo description\n\nThe main thread modifies the long variable. For the convenience of checking, the upper 4 bytes and the lower 4 bytes of the long value written each time are the same. Read the long variable in the task thread.\n\n### Problem statement\n\nIn the task thread, a long variable whose upper 4 bytes and lower 4 bytes are different is read, which is an invalid value.\n\n### Quickly run\n\n```bash\n./mvnw compile exec:java -Dexec.mainClass=fucking.concurrency.demo.InvalidLongDemo\n```\n\n## 🍺 the result of concurrency count without synchronization is wrong\n\nDemo class [`WrongCounterDemo`](src/main/java/fucking/concurrency/demo/WrongCounterDemo.java).\n\n### Demo description\n\nTwo task threads are opened in the main thread to execute concurrent incrementing counts. Main thread final result check.\n\n### Problem statement\n\nThe count value is incorrect.\n\n### Quickly run\n\n```bash\n./mvnw compile exec:java -Dexec.mainClass=fucking.concurrency.demo.WrongCounterDemo\n```\n\n## 🍺 Synchronization on mutable fields\n\nIt is common to see synchronization code on a volatile field, and the person who write it will naturally feel that this is safe and correct.  \n\\# For problem analysis, see the article [Synchronization on mutable fields](http://www.ibm.com/developerworks/library/j-concurrencybugpatterns/#N100E7).\n\nDemo class [`SynchronizationOnMutableFieldDemo`](src/main/java/fucking/concurrency/demo/SynchronizationOnMutableFieldDemo.java).\n\n### Demo description\n\nTwo task threads are opened in the main thread to execute `addListener`. Main thread final result check.\n\n### Problem statement\n\nThe final count of Listeners is incorrect.\n\n### Quickly run\n\n```bash\n./mvnw compile exec:java -Dexec.mainClass=fucking.concurrency.demo.SynchronizationOnMutableFieldDemo\n```\n\n## 🍺 Deadlock caused by the symmetric locks\n\n\\# For problem analysis, see the article [Synchronization on mutable fields](http://www.ibm.com/developerworks/library/j-concurrencybugpatterns/#N101C1)\n\nDemo class [`SymmetricLockDeadlockDemo`](src/main/java/fucking/concurrency/demo/SymmetricLockDeadlockDemo.java).\n\n### Demo description\n\nTwo task threads are opened in the main thread for execution.\n\n### Problem statement\n\nTask thread deadlocked.\n\n### Quickly run\n\n```bash\n./mvnw compile exec:java -Dexec.mainClass=fucking.concurrency.demo.SymmetricLockDeadlockDemo\n```\n\n## 🍺 Livelock caused by reentrant locks\n\n\\# For a problem description, see the paragraph about livelocks [in this article](https://www.baeldung.com/cs/deadlock-livelock-starvation#livelock)\n\nDemo class [`ReentrantLockLivelockDemo`](src/main/java/fucking/concurrency/demo/ReentrantLockLivelockDemo.java).\n\n### Demo description\n\nTwo task threads are trying to acquire a lock that the other thread holds while holding their own lock.\n\n### Problem statement\n\nWhile the threads are releasing their own lock constantly, they are also re-locking it immediately, denying the other thread\na chance to acquire both locks. Since both threads are not blocked from executing but blocked from doing meaningful work,\nthis is a livelock.\n\n### Quickly run\n\n```bash\n./mvnw compile exec:java -Dexec.mainClass=fucking.concurrency.demo.ReentrantLockLivelockDemo\n```\n\n## 🍺 Instruction reordering causes non-final field variable read error\n\nDemo class [`FinalInitialDemo`](src/main/java/fucking/concurrency/demo/FinalInitialDemo.java).\n\n### Demo description\n\nThe writer thread calls the constructor of the class, and the reader thread obtains the member variables of the non-final domain of the class.\n\n### Problem statement\n\nWhen calling the constructor, instruction reordering may occur, placing non-final domain variables outside the constructor,\ncausing the writer and reader threads to obtain the default initial values of the variables.(Instruction ordering does not necessarily occur\nand requires specific hardware and JVM environments).\n\n### Quickly run\n\n```bash\n./mvnw compile exec:java -Dexec.mainClass=fucking.concurrency.demo.FinalInitialDemo\n```\n","funding_links":[],"categories":["Java"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Foldratlee%2Ffucking-java-concurrency","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Foldratlee%2Ffucking-java-concurrency","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Foldratlee%2Ffucking-java-concurrency/lists"}