{"id":15031285,"url":"https://github.com/openhft/java-thread-affinity","last_synced_at":"2026-01-29T01:12:56.097Z","repository":{"id":41501024,"uuid":"12974177","full_name":"OpenHFT/Java-Thread-Affinity","owner":"OpenHFT","description":"Bind a java thread to a given core","archived":false,"fork":false,"pushed_at":"2024-10-23T00:51:42.000Z","size":906,"stargazers_count":1787,"open_issues_count":6,"forks_count":362,"subscribers_count":134,"default_branch":"ea","last_synced_at":"2024-10-29T11:13:27.679Z","etag":null,"topics":["affintiy","bind","core","java","low-latency"],"latest_commit_sha":null,"homepage":"http://chronicle.software/products/thread-affinity/","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/OpenHFT.png","metadata":{"files":{"readme":"README.adoc","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}},"created_at":"2013-09-20T13:34:25.000Z","updated_at":"2024-10-29T09:16:31.000Z","dependencies_parsed_at":"2023-02-17T11:40:15.024Z","dependency_job_id":"e752e439-7b3c-47fb-b46e-975c5067e403","html_url":"https://github.com/OpenHFT/Java-Thread-Affinity","commit_stats":null,"previous_names":[],"tags_count":60,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OpenHFT%2FJava-Thread-Affinity","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OpenHFT%2FJava-Thread-Affinity/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OpenHFT%2FJava-Thread-Affinity/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OpenHFT%2FJava-Thread-Affinity/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/OpenHFT","download_url":"https://codeload.github.com/OpenHFT/Java-Thread-Affinity/tar.gz/refs/heads/ea","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247918919,"owners_count":21018044,"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":["affintiy","bind","core","java","low-latency"],"created_at":"2024-09-24T20:15:21.876Z","updated_at":"2026-01-29T01:12:56.090Z","avatar_url":"https://github.com/OpenHFT.png","language":"Java","readme":"= Thread Affinity\n\nimage::docs/images/Thread-Affinity_line.png[width=20%]\n\n== Version\n\n[#image-maven]\n[caption=\"\",link=https://maven-badges.herokuapp.com/maven-central/net.openhft/affinity]\nimage::https://maven-badges.herokuapp.com/maven-central/net.openhft/affinity/badge.svg[]\nimage:https://javadoc.io/badge2/net.openhft/affinity/javadoc.svg[link=\"https://www.javadoc.io/doc/net.openhft/affinity/latest/index.html\"]\n\n== Overview\nLets you bind a thread to a given core, this can improve performance (this library works best on linux).\n\nOpenHFT Java Thread Affinity library\n\nSee https://github.com/OpenHFT/Java-Thread-Affinity/tree/master/affinity/src/test/java[affinity/src/test/java]\nfor working examples of how to use this library.\n\n=== Supported operating systems\n\nThe library detects the running platform in `Affinity.java` and selects an implementation for that OS.\nFeatures differ between systems:\n\n* *Linux* - full affinity control via JNA.\nThe implementation can get and set thread affinity, query the current CPU, and obtain process and thread IDs.\n* *Windows* - thread affinity is managed through the kernel API.\nProcess and thread IDs are available, while `getCpu()` returns `-1`.\n* *macOS* - provides process and thread IDs but does not modify affinity and reports the CPU id as `-1`.\n* *Solaris* - mirrors the macOS implementation: only process and thread IDs are returned with no affinity or CPU querying support.\n\n=== Changes\n\n* V3.2.0 - Add support for text configuration\n* V3.1.1 - Upgraded JNA dependency to 4.4.0\n* V2.0.1 - Added getThreadId for the process if of the thread.\n\n=== Dependencies\n\nJava-Thread-Affinity will try to use link:https://github.com/java-native-access/jna[JNA]\nto provide access to native thread-handling functions.\nJNA should be installed on your system to get the most from this library.\n\n=== JNA version\n\nJava-Thread-Affinity currently depends on JNA version 4.4.0, which in turn depends on a version of GLIBC \u003e= 2.14. If your operating system is an old one, with a version of GLIBC released before 2011, this library will not be able to invoke native functions.\n\nTo work around this problem, fork the repository, and override the `\u003cversion\u003e` tag for the artifacts `jna` and `jna-platform` in the project's `pom` file.\n\n=== Installing JNA on Ubuntu\n\n    sudo apt-get install libjna-java\n\n=== Installing JNA on CentOS\n\n    sudo yum install jna\n\n=== Installing JNA on Windows\n\n    choco install jna\n\nOr download jna.jar and jna-platform.jar from the JNA project and add them to your classpath.\n\n=== How does CPU allocation work?\nThe library will read your `/proc/cpuinfo` if you have one or provide one and it will determine your CPU layout.\nIf you don't have one it will assume every CPU is on one CPU socket.\n\nThe library looks for isolated CPUs determined by looking at the CPUs you are not running on by default.\ni.e. if you have 16 CPUs but 8 of them are not available for general use (as determined by the affinity of the process on startup) it will start assigning to those CPUs.\n\nNote: if you have more than one process using this library you need to specify which CPUs the process can use otherwise it will assign the same CPUs to both processes.\n\nTo control which CPUs a process can use, add `-Daffinity.reserved={cpu-mask-in-hex}` to the command line of the process.\nThe mask is a hexadecimal bit mask without the `0x` prefix where bit `0` represents CPU `0`, bit `1` represents CPU `1` and so on.\nMultiple CPUs can be specified by setting more than one bit.\n\nFor example:\n\n* `-Daffinity.reserved=2` reserves only CPU `1`.\n* `-Daffinity.reserved=6` reserves CPUs `1` and `2`.\n* `-Daffinity.reserved=10` reserves CPUs `1` and `3` (hexadecimal `a`).\n\nUse an appropriate mask when starting each process to avoid reserving the same cores for multiple JVMs.\n\nNote: the CPU 0 is reserved for the Operating System, it has to run somewhere.\n\n=== References\n\nhttps://github.com/peter-lawrey/Java-Thread-Affinity/wiki/Getting-started\n\nhttps://github.com/peter-lawrey/Java-Thread-Affinity/wiki/How-it-works\n\nhttps://vanillajava.blogspot.com/2013/07/micro-jitter-busy-waiting-and-binding.html\n\n=== isolcpus\n\nJava-Thread-Affinity requires that you first isolate some CPU's.\n\nOnce a CPU core is isolated, the Linux scheduler will not use the CPU core to run any user-space processes.\nThe isolated CPUs will not participate in load balancing, and will not have tasks running on them unless explicitly assigned.\n\nTo isolate the 1st and 3rd CPU cores (CPU numbers start from 0) on your system, add the following to the kernel command line during boot:\n\nisolcpus=1,3\n\n.Using GRUB\n[source]\n----\nsudo sed -i 's/^GRUB_CMDLINE_LINUX_DEFAULT=\"/GRUB_CMDLINE_LINUX_DEFAULT=\"isolcpus=1,3 /' /etc/default/grub\nsudo update-grub\nsudo reboot\n----\n\n.Using systemd-boot\n[source]\n----\nsudo sed -i 's/^options \\(.*\\)/options \\1 isolcpus=1,3/' /boot/loader/entries/*.conf\nsudo reboot\n----\n\n== Using AffinityLock\n\n=== Acquiring a CPU lock for a thread\nYou can acquire a lock for a CPU in the following way:\n\n.In Java 6\n[source,java]\n----\nAffinityLock al = AffinityLock.acquireLock();\ntry {\n     // do some work locked to a CPU.\n} finally {\n     al.release();\n}\n----\n\n.In Java 7 or 8\n[source,java]\n----\ntry (AffinityLock al = AffinityLock.acquireLock()) {\n    // do some work while locked to a CPU.\n}\n----\n\nYou have further options such as\n\n=== Acquiring a CORE lock for a thread\nYou can reserve a whole core.\nIf you have hyper-threading enabled, this will use one CPU and leave it's twin CPU unused.\n\n[source,java]\n----\ntry (AffinityLock al = AffinityLock.acquireCore()) {\n    // do some work while locked to a CPU.\n}\n----\n\n=== Controlling layout\n\nYou can chose a layout relative to an existing lock.\n\n[source,java]\n----\ntry (final AffinityLock al = AffinityLock.acquireLock()) {\n    System.out.println(\"Main locked\");\n    Thread t = new Thread(new Runnable() {\n        @Override\n        public void run() {\n            try (AffinityLock al2 = al.acquireLock(AffinityStrategies.SAME_SOCKET,\n                                                   AffinityStrategies.ANY)) {\n                 System.out.println(\"Thread-0 locked\");\n            }\n        }\n    });\n    t.start();\n}\n----    \n\nIn this example, the library will prefer a free CPU on the same Socket as the first thread, otherwise it will pick any free CPU.\n\n=== Affinity strategies\nThe `AffinityStrategies` enum defines hints for selecting a CPU relative to an existing lock.\n\n[options=\"header\",cols=\"1,3\"]\n|===\n| Strategy | Meaning\n\n|`ANY`|Use any available CPU.\n|`SAME_CORE`|Select a CPU on the same core.\n|`SAME_SOCKET`|Select a CPU on the same socket but a different core.\n|`DIFFERENT_CORE`|Select a CPU on another core (possibly another socket).\n|`DIFFERENT_SOCKET`|Select a CPU on a different socket.\n|===\n\n=== Getting the thread id\nYou can get the current thread id using\n\n[source,java]\n----\nint threadId = AffinitySupport.getThreadId();\n----\n\n=== Determining which CPU you are running on\nYou can get the current CPU being used by\n\n[source,java]\n----\nint cpuId = AffinitySupport.getCpu();\n----\n\n=== Controlling the affinity more directly\n\nThe affinity of the process on start up is\n\n[source,java]\n----\nlong baseAffinity = AffinityLock.BASE_AFFINITY;\n----   \n\nThe available CPU for reservation is\n\n[source,java]\n----\nlong reservedAffinity = AffinityLock.RESERVED_AFFINITY;\n----    \n\nIf you want to get/set the affinity directly you can do\n\n[source,java]\n----\nlong currentAffinity = AffinitySupport.getAffinity();\nAffinitySupport.setAffinity(1L \u003c\u003c 5); // lock to CPU 5.\n----\n\n=== Understanding dumpLocks() output\n\nSeveral examples print the current CPU assignments using `AffinityLock.dumpLocks()`.\nEach line of the output begins with the zero based CPU id followed by the status of that CPU.\nExample output might look like:\n\n[source]\n----\n0: Reserved for this application\n1: Thread[reader,5,main] alive=true\n2: General use CPU\n3: CPU not available\n----\n\nThe number on each line is the logical CPU index as recognised by the library.\nThe text after the colon describes whether that CPU is free, reserved or already bound to a thread.\nUse these indices when calling `AffinityLock.acquireLock(n)`\nor when constructing explicit affinity masks.\n\n=== Lock file directory\n\nAffinityLock stores a small lock file for each CPU.\nThese files are placed in the directory specified by the `java.io.tmpdir` system property, which by default points to your system's temporary directory (usually `/tmp` on Linux).\n\nIf you want to keep the lock files elsewhere, set this property before using any affinity APIs:\n\n[source,bash]\n----\njava -Djava.io.tmpdir=/path/to/dir ...\n----\n\nor in code\n\n[source,java]\n----\nSystem.setProperty(\"java.io.tmpdir\", \"/path/to/dir\");\n----\n\n=== Debugging affinity state\n\nFor a detailed of view of the current affinity state (as seen by the library), execute the following script on Linux systems:\n\n[source]\n----\n# change to the affinity lock-file directory (defaults to system property java.io.tmpdir)\n$ cd /tmp\n\n# dump affinity state\n$ for i in \"$(ls cpu-*)\"; \n      do PID=\"$(cat $i | head -n1)\"; TIMESTAMP=\"$(cat $i | tail -n1)\"; \n      echo \"pid $PID locked at $TIMESTAMP in $i\"; taskset -cp $PID; \n      cat \"/proc/$PID/cmdline\"; echo; echo \n  done\n\n  pid 14584 locked at 2017.10.30 at 10:33:24 GMT in cpu-3.lock\n  pid 14584's current affinity list: 3\n  /opt/jdk1.8.0_141/bin/java ...\n\n----\n\n== Using AffinityThreadFactory\n\n`AffinityThreadFactory` binds each thread it creates according to a set of `AffinityStrategy` rules.\nThis allows executors to automatically run tasks on cores selected by the library.\n\n[source,java]\n----\nExecutorService es = Executors.newFixedThreadPool(4,\n        new AffinityThreadFactory(\"worker\",\n                AffinityStrategies.SAME_CORE,\n                AffinityStrategies.DIFFERENT_SOCKET,\n                AffinityStrategies.ANY));\nes.submit(() -\u003e {\n    // your task here\n});\nSystem.out.println(\"\\nThe assignment of CPUs is\\n\" + AffinityLock.dumpLocks());\n----\n\n== Support Material\n\nhttps://groups.google.com/forum/?hl=en-GB#!forum/java-thread-affinity[Java Thread Affinity support group]\n\nFor an article on how much difference affinity can make and how to use it http://vanillajava.blogspot.com/2013/07/micro-jitter-busy-waiting-and-binding.html\n\n== Questions and Answers\n\n=== Question: How to lock a specific cpuId\nI am currently working on a project related to deadlock detection in multithreaded programs in java.\nWe are trying to run threads on different processors and thus came across your github posts regarding the same. https://github.com/peter-lawrey/Java-Thread-Affinity/wiki/Getting-started\nBeing a beginner, I have little knowledge and thus need your assistance.\nWe need to know how to run threads on specified cpu number and then switch threads when one is waiting.\n\n=== Answer\n\n[source,java]\n----\n// lock a cpuId\ntry (AffinityLock lock = AffinityLock.acquireLock(n)) {\n\n}\n----\n\nwhere n is the cpu you want to run the thread on.\n\nOR\n\n[source,java]\n----\n// lock one of the last CPUs\ntry (AffinityLock lock = AffinityLock.acquireLockLastMinus(n)) {\n\n}\n----\n\n=== Question: how to use a configuration file to set the cpuId\n\nI have the cpuId in a configuration file, how can I set it using a string?\n\n=== Answer: use one of the following\n\n[source,java]\n----\ntry (AffinityLock lock = AffinityLock.acquireLock(\"last\")) {\n    assertEquals(PROCESSORS - 1, Affinity.getCpu());\n}\ntry (AffinityLock lock = AffinityLock.acquireLock(\"last-1\")) {\n    assertEquals(PROCESSORS - 2, Affinity.getCpu());\n}\ntry (AffinityLock lock = AffinityLock.acquireLock(\"1\")) {\n    assertEquals(1, Affinity.getCpu());\n}\ntry (AffinityLock lock = AffinityLock.acquireLock(\"any\")) {\n    assertTrue(lock.bound);\n}\ntry (AffinityLock lock = AffinityLock.acquireLock(\"none\")) {\n    assertFalse(lock.bound);\n}\ntry (AffinityLock lock = AffinityLock.acquireLock((String) null)) {\n    assertFalse(lock.bound);\n}\ntry (AffinityLock lock = AffinityLock.acquireLock(\"0\")) { // prints a warning\n    assertFalse(lock.bound);\n}\n----\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fopenhft%2Fjava-thread-affinity","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fopenhft%2Fjava-thread-affinity","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fopenhft%2Fjava-thread-affinity/lists"}